package cn.com.ejiakanghu.service;

import cn.com.ejiakanghu.config.LocationContext;
import cn.com.ejiakanghu.core.exceptions.BizException;
import cn.com.ejiakanghu.core.utils.RespUtil;
import cn.com.ejiakanghu.core.vo.BaseResult;
import cn.com.ejiakanghu.dto.*;
import cn.com.ejiakanghu.form.CreateOrderForm;
import cn.com.ejiakanghu.form.FreightForecastForm;
import cn.com.ejiakanghu.form.WeixinSubGoodsArrivedForm;
import cn.com.ejiakanghu.goods.dto.GoodsTag;
import cn.com.ejiakanghu.vo.SubOrderGoodsVo;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.github.pagehelper.PageInfo;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.linlinjava.litemall.core.system.SystemConfig;
import org.linlinjava.litemall.core.util.InventoryUtil;
import org.linlinjava.litemall.core.util.JacksonUtil;
import org.linlinjava.litemall.db.config.WxPayScoreConfig;
import org.linlinjava.litemall.db.dao.*;
import org.linlinjava.litemall.db.dao.app.AppGoodsMapper;
import org.linlinjava.litemall.db.dao.order_manage.AgedmallOnlineMapper;
import org.linlinjava.litemall.db.domain.*;
import org.linlinjava.litemall.db.jsonfield.AgedmallLeaseRuleConfRuleInfo;
import org.linlinjava.litemall.db.jsonfield.LitemallGoodsProductSpecification;
import org.linlinjava.litemall.db.jsonfield.ServiceTime;
import org.linlinjava.litemall.db.service.*;
import org.linlinjava.litemall.db.service.AgedmallOnlinesService;
import org.linlinjava.litemall.db.util.*;
import org.linlinjava.litemall.db.vo.app.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author houzb
 * @Description
 * @create 2021-04-04 17:00
 */
@Component
public class GoodsManager {
    private Logger logger = LoggerFactory.getLogger(GoodsManager.class);

    @Autowired
    private LitemallSearchHistoryService searchHistoryService;
    @Autowired
    private LitemallGoodsService goodsService;
    @Autowired
    private AgedmallGoodsSaleInfoService goodsSaleInfoService;

    @Autowired
    private LitemallCategoryService categoryService;

    @Autowired
    private LitemallGoodsProductService productService;

    @Autowired
    private LitemallCollectService collectService;

    @Autowired
    private LitemallGoodsSpecificationService goodsSpecificationService;

    @Autowired
    private AgedmallGoodsDeductionConfService agedmallGoodsDeductionConfService;
    @Autowired
    private AgedmallReplenishNoticeService agedmallReplenishNoticeService;
    @Autowired
    private AgedmallLeaseRuleConfService agedmallLeaseRuleConfService;
    @Autowired
    private AgedmallGoodsGroupShipService agedmallGoodsGroupShipService;
    @Autowired
    private AgedmallGoodsSpecificationInfoService agedmallGoodsSpecificationInfoService;
    @Autowired
    private AgedmallGoodsPartsService agedmallGoodsPartsService;
    @Autowired
    private LitemallGoodsProductService litemallGoodsProductService;
    @Autowired
    private LitemallAddressService addressService;
    @Autowired
    private AgedmallStoreService agedmallStoreService;
    @Autowired
    private OrderManager orderManager;
    @Autowired
    private LitemallGoodsAttributeService litemallGoodsAttributeService;
    @Autowired
    private AgedmallStoreGoodsService agedmallStoreGoodsService;
    @Autowired
    private AgedmallExplainService agedmallExplainService;
    @Autowired
    private AgedmallChargeTemplateService agedmallChargeTemplateService;
    @Autowired
    private AgedmallFreightTemplateService agedmallFreightTemplateService;
    @Autowired
    private LitemallRegionService litemallRegionService;
    @Autowired
    private AgedmallHospitalSendService agedmallHospitalSendService;
    @Autowired
    private AgedmallUserInfoService agedmallUserInfoService;
    @Autowired
    private OrderCalcService orderCalcService;
    @Autowired
    private AgedmallOnlinesService agedmallOnlineService;
    @Autowired
    private AgedmallOnlineServiceProductService agedmallOnlineServiceProductService;
    @Resource
    private AgedmallTagsMapper agedmallTagsMapper;
    @Autowired
    private AgedmallOnlinesService agedmallOnlinesService;
    @Resource
    private AgedmallGoodsOnlineServiceMapper agedmallGoodsOnlineServiceMapper;
    @Resource
    private AgedmallDepartmentMapper agedmallDepartmentMapper;
    @Resource
    private AgedmallOnlineMapper agedmallOnlineMapper;
    @Resource
    private AgedmallHospitalSendMapper agedmallHospitalSendMapper;
    @Resource
    private LogManager logManager;
    @Resource
    private AgedmallHospitalSendGoodsAttributeMapper agedmallHospitalSendGoodsAttributeMapper;
    @Resource
    private AgedmallHospitalSendStoreAttributeMapper agedmallHospitalSendStoreAttributeMapper;

    @Resource
    private AppGoodsMapper appGoodsMapper;

    @Resource
    private AgedmallSubscribeToInformMapper agedmallSubscribeToInformMapper;

    @Resource
    private LitemallGoodsMapper litemallGoodsMapper;

    @Resource
    private LitemallRegionMapper litemallRegionMapper;


    @Resource
    private LitemallGoodsProductMapper litemallGoodsProductMapper;


    @Resource
    private LitemallUserMapper litemallUserMapper;

    @Resource
    private CartManager cartManager;

    @Resource
    private AgedmallChargeTemplateLeasePeriodMapper agedmallChargeTemplateLeasePeriodMapper;



    public int getCategoryIdByGoodsType(String goodsType) {
        if (StringUtils.isEmpty(goodsType) || "".equals(goodsType)) {
            return 0;
        }
        String categoryName = EnumGoodsType.getTypeNameByType(goodsType);
        LitemallCategory category = categoryService.findByName(categoryName);
        return category == null ? 0 : category.getId();
    }


    public List<Integer> getHospitalGoodsList(Integer hosId,
                                              Integer hosGoodsType,
                                              String hosLinkCode,
                                              Integer saleUserId) {
        List<Integer> goodsList;
        if (hosId != null) {
            goodsList = appGoodsMapper.getHospitalGoods(hosId, hosGoodsType);
        } else {
            goodsList = new ArrayList<>();
        }
        return goodsList;
    }

    public List<Integer> getHospitalStoreList(Integer hosId) {
        List<Integer> storeList = new ArrayList<>();
        if (hosId != null) {
            AgedmallHospitalSend hospitalSend = agedmallHospitalSendMapper.selectByPrimaryKey(hosId);
            String[] split = hospitalSend.getStoreIds().split(",");
            for (int i = 0; i < split.length; i++) {
                storeList.add(Integer.parseInt(split[i]));
            }
        }
        return storeList;
    }

    public BaseResult list(Integer storeId, Integer categoryId, String goodsType,
                           Integer brandId,
                           String keyword,
                           Boolean isNew,
                           Boolean isHot, Integer userId, Integer page, Integer limit, String sort, String order,
                           Integer hosId,
                           Integer hosGoodsType,
                           String hosLinkCode,
                           Integer saleUserId) {
        //添加到搜索历史
        if (userId != null && !StringUtils.isEmpty(keyword)) {
            LitemallSearchHistory searchHistoryVo = new LitemallSearchHistory();
            searchHistoryVo.setKeyword(keyword);
            searchHistoryVo.setUserId(userId);
            searchHistoryVo.setFrom("wx");
            searchHistoryService.save(searchHistoryVo);
        }
        //查询列表数据
        Location location = LocationContext.get();
        List<Integer> hospitalGoodsList = getHospitalGoodsList(hosId, hosGoodsType, hosLinkCode, saleUserId);

        List<Integer> goodsIds = goodsService.queryList(location.getProvince(), location.getCity(), storeId, categoryId, goodsType, brandId,
                keyword, isHot, isNew, page, limit, sort, order, hospitalGoodsList);
        PageInfo<Integer> pagedList = PageInfo.of(goodsIds);
        List<Integer> hospitalStoreList = getHospitalStoreList(hosId);
        List<StoreGoodsVo> goodsList = getNearestStoreGoodsList(goodsIds, location.getLng(), location.getLat(), location.getCity(), hospitalStoreList);
        List<GoodsBaseData> goodsBaseDataList = new ArrayList<>();
        goodsList.stream().forEach(g -> {
            // 租赁商品 商品价格为收费规格起始价
            if (GoodsConstant.GOODS_TYPE_LEASE.equals(g.getGoodsType())) {
                AgedmallChargeTemplateLeasePeriodExample leasePeriodExample=new AgedmallChargeTemplateLeasePeriodExample();
                leasePeriodExample.setOrderByClause("id ASC");
                leasePeriodExample.createCriteria().andDeletedEqualTo(false).andCustomTemplateIdEqualTo(g.getLeaseChargeTemolateId());
                AgedmallChargeTemplateLeasePeriod agedmallChargeTemplateLeasePeriod = agedmallChargeTemplateLeasePeriodMapper.selectOneByExampleWithBLOBs(leasePeriodExample);
                if (null != agedmallChargeTemplateLeasePeriod) {
                    g.setSaleRetailPrice(agedmallChargeTemplateLeasePeriod.getBasePrice());
                }
            }
            // 是否支持医院小时达
            List<AgedmallHospitalSend> hospitalSends = agedmallHospitalSendService.getByStoreAndGoods(g.getStoreId(), g.getId());
            g.setIsHospital(hospitalSends.size() > 0 ? 1 : 0);
            GoodsBaseData goodsBaseData = GoodsBaseData.getInstance(g);
            // 抵扣金
            BigDecimal deductNum = agedmallGoodsDeductionConfService.getDeductNumByGoods(g);
            if (null != deductNum) {
                goodsBaseData.setDeductNum(deductNum.doubleValue());
            }
            goodsBaseDataList.add(goodsBaseData);

        });
        PageData<GoodsBaseData> pageData = new PageData<>();
        pageData.setRows(pagedList.getPages()<page?null:goodsBaseDataList);
        pageData.setNowPage(page);
        pageData.setTotalRows((int) pagedList.getTotal());
        pageData.setTotalPage(pagedList.getPages());

        return RespUtil.success(pageData);
    }


    /**
     * 获取sku信息
     *
     * @param userId
     * @param id
     * @return
     */
    public BaseResult getSkuInfo(Integer userId, Integer id) {
        StoreGoodsVo info = agedmallStoreGoodsService.getStoreGoodsById(id);
        if (info == null) {
            return RespUtil.badArgumentValue();
        }

        Map<String, Object> data = new HashMap<>();
        //商品基本信息 goods_base
        GoodsBaseData goodsBaseData = getGoodsBase(info);
        data.put("goods_base", goodsBaseData);

        GoodsSku goodsSku = getSkuItemList(info);
        data.put("goods_sku", goodsSku);

        return RespUtil.success(data);
    }

    /**
     * 商品详情
     *
     * @param userId
     * @param id
     * @return
     */
    public BaseResult detail(Integer userId, Integer id, Integer channel) {
        // 门店商品信息
        StoreGoodsVo info = agedmallStoreGoodsService.getStoreGoodsById(id);
        if (info == null) {
            return RespUtil.badArgumentValue();
        }

        logManager.recordGoodsViewLog(userId, info);

        Map<String, Object> data = new HashMap<>();
        //商品基本信息 goods_base
        GoodsBaseData goodsBaseData = getGoodsBase(info);
        data.put("goodsBase", goodsBaseData);

        //商品详情信息 goods_detail
        GoodsDetailData detailData = getGoodsDetail(info, userId);
        data.put("goodsDetail", detailData);

        AgedmallStore agedmallStore = agedmallStoreService.findStoreById(info.getStoreId());
        // 租赁商品独有信息 goods_lease
        if (GoodsConstant.GOODS_TYPE_LEASE.equals(info.getGoodsType())) {
            GoodsLeaseData leaseData = new GoodsLeaseData();
            AgedmallChargeTemplate agedmallChargeTemplate = agedmallChargeTemplateService.findById(info.getLeaseChargeTemolateId());
            if (null != agedmallChargeTemplate) {
                AgedmallChargeTemplateLeasePeriodExample leasePeriodExample=new AgedmallChargeTemplateLeasePeriodExample();
                leasePeriodExample.setOrderByClause("id ASC");
                leasePeriodExample.createCriteria().andDeletedEqualTo(false).andCustomTemplateIdEqualTo(info.getLeaseChargeTemolateId());
                List<AgedmallChargeTemplateLeasePeriod> agedmallChargeTemplateLeasePeriod = agedmallChargeTemplateLeasePeriodMapper.selectByExampleWithBLOBs(leasePeriodExample);
                List<GoodsLeaseRuleInfo> goodsLeaseRuleInfoList=new ArrayList<>();
                for (int i = 0; i < agedmallChargeTemplateLeasePeriod.size(); i++) {
                    GoodsLeaseRuleInfo leaseRuleInfo=new GoodsLeaseRuleInfo(agedmallChargeTemplateLeasePeriod.get(i));
                    leaseRuleInfo.setMaxFee(agedmallChargeTemplate.getTopPrice());
                    leaseRuleInfo.setMinDays(agedmallChargeTemplateLeasePeriod.get(i).getBaseDay());
                    leaseRuleInfo.setType("ladder");
                    goodsLeaseRuleInfoList.add(leaseRuleInfo);
                }

                leaseData.setRuleInfo(goodsLeaseRuleInfoList);
            }

            AgedmallExplain agedmallExplain = agedmallExplainService.findByBusId(agedmallStore.getBusiId(), 0);
            if (null != agedmallExplain) {
                leaseData.setLeaseHtml(agedmallExplain.getContent());
            }

            leaseData.setCreditLease(info.getCreditLease());
            leaseData.setCreditScore(WxPayScoreConfig.MIN_SCORE);
            data.put("goodsLease", leaseData);
        }

        //商品店铺信息 goods_store
        GoodsStoreInfo storeInfo = GoodsStoreInfo.getInstance(agedmallStore);
        // 获取上架售卖和租赁商品数
        int saleGoodsCount = goodsService.countByStoreId(agedmallStore.getId().intValue(), GoodsConstant.GOODS_TYPE_SALE);
        int leaseGoodsCount = goodsService.countByStoreId(agedmallStore.getId().intValue(), GoodsConstant.GOODS_TYPE_LEASE);
        storeInfo.setLeaseGoodsCount(leaseGoodsCount);
        storeInfo.setSaleGoodsCount(saleGoodsCount);

        data.put("goodsStore", storeInfo);

        // 商品SKU信息 goods_sku (里面增加商品服务信息 serviceSpec)
        GoodsSku goodsSku = getSkuItemList(info);
        data.put("goodsSku", goodsSku);

        List<GoodsHospitalInfo> hospitalInfos = getHospitalInfo(info, channel);
        data.put("hospitalList", hospitalInfos);

        return RespUtil.success(data);
    }

    private List<GoodsHospitalInfo> getHospitalInfo(StoreGoodsVo storeGoodsVo, Integer channel) {
        List<AgedmallHospitalSend> hospitalSends = agedmallHospitalSendService.getByStoreAndGoods(storeGoodsVo.getStoreId(), storeGoodsVo.getId());
        List<GoodsHospitalInfo> goodsHospitalInfos = hospitalSends.stream().map(GoodsHospitalInfo::new).collect(Collectors.toList());
        for (int i = 0; i < goodsHospitalInfos.size(); i++) {
            GoodsHospitalDeliveryMode goodsHospitalDeliveryMode = assambleDeliveryMode(goodsHospitalInfos.get(i), channel,storeGoodsVo);
            goodsHospitalInfos.get(i).setDeliveryMode(goodsHospitalDeliveryMode);
        }
        return goodsHospitalInfos;
    }

    public GoodsHospitalDeliveryMode assambleDeliveryMode(GoodsHospitalInfo goodsHospitalInfo,Integer channel,StoreGoodsVo storeGoodsVo){
        GoodsHospitalDeliveryMode deliveryMode ;
        AgedmallHospitalSendGoodsAttributeExample goodsAttributeExample=new AgedmallHospitalSendGoodsAttributeExample();
        goodsAttributeExample.createCriteria().andGoodsIdEqualTo(storeGoodsVo.getId().longValue()).andHospitalSendIdEqualTo(goodsHospitalInfo.getId().longValue());
        AgedmallHospitalSendGoodsAttribute goodsAttribute = agedmallHospitalSendGoodsAttributeMapper.selectOneByExample(goodsAttributeExample);
        AgedmallHospitalSendStoreAttributeExample storeAttributeExample=new AgedmallHospitalSendStoreAttributeExample();
        storeAttributeExample.createCriteria().andStoreIdEqualTo(storeGoodsVo.getStoreId().longValue()).andHospitalSendIdEqualTo(goodsHospitalInfo.getId().longValue());
        AgedmallHospitalSendStoreAttribute storeAttribute = agedmallHospitalSendStoreAttributeMapper.selectOneByExample(storeAttributeExample);
        String[] carerSendSplit=null;
        if(ObjectUtil.isNotNull(goodsAttribute)&&StringUtils.isNotBlank(goodsAttribute.getCarerSendType())){
            carerSendSplit=goodsAttribute.getCarerSendType().split(",");
        }
        switch (channel){
            case 0:
            case 2:
            case 3:
                deliveryMode = assambleDeliveryData(0, carerSendSplit, goodsHospitalInfo,0);
                break;
            case 1:
                //如果门店也支持到桩自提
                if(ObjectUtil.isNotNull(storeAttribute)&&"1".equals(storeAttribute.getSendType())){
                    //TODO 到桩自提
                    deliveryMode = assambleDeliveryData(1,carerSendSplit,goodsHospitalInfo,1);
                }
                else{
                    deliveryMode = assambleDeliveryData(0,carerSendSplit,goodsHospitalInfo,0);
                }
                break;
            default:
                deliveryMode=new GoodsHospitalDeliveryMode();
                break;
        }
        //只有租赁支持送货到桩
        if(storeGoodsVo.getGoodsType().equals("sale")){
            deliveryMode.setSubHospitalSelf(null);
        }
        return deliveryMode;
    }

    /**
     * 是否医院 0- 否 1-是
     * @param isHospital
     * @return
     */
    public GoodsHospitalDeliveryMode assambleDeliveryData(Integer isHospital,String[] sendTypeList,GoodsHospitalInfo goodsHospitalInfo,Integer storeHospitalSelf){
        GoodsHospitalDeliveryMode deliveryMode = new GoodsHospitalDeliveryMode();

        if(sendTypeList == null ){
            return deliveryMode;
        }
        for (int i = 0; i < sendTypeList.length; i++) {
            GoodsHospitalDeliveryData deliveryData=new GoodsHospitalDeliveryData();

            String sendType=sendTypeList[i];
            if(isHospital==0){
                switch (sendType){
                    case "0":
                        deliveryData.setName("今日小时达");
                        deliveryData.setHour(goodsHospitalInfo.getHour());
                        deliveryData.setPrice(goodsHospitalInfo.getPrice());
                        deliveryMode.setDayHourReach(deliveryData);
                        break;
                    case "1":
                        deliveryData.setName("预约门店自提");
                        deliveryData.setDay(goodsHospitalInfo.getSubDay());
                        deliveryMode.setSubStoreSelf(deliveryData);
                        break;
                    case "2":
                        deliveryData.setName("今日门店自提");
                        deliveryMode.setDayStoreSelf(deliveryData);
                        break;
                    case "3":
                        deliveryData.setName("预约小时达");
                        deliveryData.setDay(goodsHospitalInfo.getSubDay());
                        deliveryMode.setSubHourReach(deliveryData);
                        break;
                }
            }
            else{
                switch (sendType){
                    case "0":
                        deliveryData.setName("今日小时达");
                        deliveryData.setHour(goodsHospitalInfo.getHour());
                        deliveryData.setPrice(goodsHospitalInfo.getPrice());
                        deliveryMode.setDayHourReach(deliveryData);
                        break;
                    case "1":
                        if(storeHospitalSelf==1){
                        deliveryData.setName("预约到院自提");
                        deliveryData.setDay(goodsHospitalInfo.getSubDay());
                        deliveryMode.setSubHospitalSelf(deliveryData);
                        }
                        break;
                }
            }
        }

        return deliveryMode;
    }



    private FreightRule getFreightRule(StoreGoodsVo storeGoodsVo, AgedmallStore agedmallStore) {
        FreightRule freightRule = new FreightRule();
        freightRule.setSelfPickup(agedmallStore.getSupportSelfDelivery());

        FreightExpressRule expressRule = new FreightExpressRule();
        expressRule.setIsFixed(1 - storeGoodsVo.getLogisticsType());
        // 固定收费
        if (0 == storeGoodsVo.getLogisticsType()) {
            expressRule.setFixedCharge(storeGoodsVo.getExpressCost());
            // 模板收费
        } else {
            Integer express = storeGoodsVo.getExpress();
            AgedmallFreightTemplate freightTemplate = express != null ? agedmallFreightTemplateService.findById(express.longValue()) : null;
            if (null != freightTemplate) {
                expressRule.setBillingMethod(freightTemplate.getPayType());
                List<LitemallRegion> regions = litemallRegionService.getProvinces();
                Map<Integer, String> regionMap = regions.stream().collect(Collectors.toMap(LitemallRegion::getId, LitemallRegion::getName));
                List<FreightExpressDistributionArea> areas = JSONArray.parseArray(freightTemplate.getExpressTemplate(), FreightExpressDistributionArea.class);
                if(areas != null) {
                    areas.stream().forEach(p -> {
                        String result = "";
                        String ids = p.getRegion();
                        String[] idArr = ids.split(",");
                        for (String s : idArr) {
                            result += "," + regionMap.get(Integer.parseInt(s));
                        }
                        p.setRegion(result.replaceFirst(",", ""));
                    });
                }else {
                    areas = new ArrayList<>();
                }
                expressRule.setDistributionArea(areas);
            }
        }
        freightRule.setExpressRule(expressRule);

        FreightSameCityRule sameCityRule = new FreightSameCityRule();
        sameCityRule.setIsFixed(1 - storeGoodsVo.getLogisticsType());
        // 固定收费
        if (0 == storeGoodsVo.getLogisticsType()) {
            sameCityRule.setFixedCharge(storeGoodsVo.getSameCityCost());
            // 模板收费
        } else {
            Integer sameCity = storeGoodsVo.getSameCity();
            AgedmallFreightTemplate freightTemplate = sameCity != null ? agedmallFreightTemplateService.findById(sameCity.longValue()) : null;
            if (null != freightTemplate) {
                sameCityRule.setBillingMethod(freightTemplate.getPayType());
                // 按区域
                if (1 == freightTemplate.getPayType()) {
                    FreightSameCityDistributionArea distributionArea = new FreightSameCityDistributionArea();
                    distributionArea.setRadiusKm(freightTemplate.getDeliveryRange());
                    distributionArea.setRadiusCharge(freightTemplate.getFixedPay());
                    distributionArea.setNormalWeight(freightTemplate.getWeight());
                    distributionArea.setEveryWeight(freightTemplate.getWeightAfterUnit());
                    distributionArea.setEveryWeightCharge(freightTemplate.getWeightAfterUnitPay());
                    distributionArea.setSlowTime(freightTemplate.getSendSlowestTime().intValue());
                    distributionArea.setFastTime(freightTemplate.getSendFastestTime().intValue());
                    distributionArea.setSubscribe(freightTemplate.getCanAppointment());
                    distributionArea.setUrgent(freightTemplate.getCanUrgent());
                    sameCityRule.setDistributionArea(distributionArea);
                    // 按距离
                } else {
                    FreightSameCityDistributionDistance distributionDistance = new FreightSameCityDistributionDistance();
                    distributionDistance.setMaxKm(freightTemplate.getDeliveryRange());
                    distributionDistance.setDistanceKm(freightTemplate.getSameCityFirstUnit());
                    distributionDistance.setDistanceCharge(freightTemplate.getSameCityFirstUnitPay());
                    distributionDistance.setEveryDistance(freightTemplate.getSameCityAfterUnit());
                    distributionDistance.setEveryDistanceCharge(freightTemplate.getSameCityAfterUnitPay());
                    distributionDistance.setEveryWeight(freightTemplate.getWeightAfterUnit());
                    distributionDistance.setEveryWeightCharge(freightTemplate.getWeightAfterUnitPay());
                    distributionDistance.setNormalWeight(freightTemplate.getWeight());
                    distributionDistance.setSlowTime(freightTemplate.getSendSlowestTime().intValue());
                    distributionDistance.setFastTime(freightTemplate.getSendFastestTime().intValue());
                    distributionDistance.setSubscribe(freightTemplate.getCanAppointment());
                    distributionDistance.setUrgent(freightTemplate.getCanUrgent());
                    sameCityRule.setDistributionDistance(distributionDistance);
                }
            }
        }
        freightRule.setSameCityRule(sameCityRule);

        FreightFeeRule feeRule = new FreightFeeRule();
        feeRule.setDeliveryType(storeGoodsVo.getFreight());
        feeRule.setDeliveryPrice(storeGoodsVo.getFreightCondition());
        feeRule.setDeliveryDay(storeGoodsVo.getFreeDeliveryDay());
        feeRule.setPickupType(storeGoodsVo.getPickFreight());
        feeRule.setPickupPrice(storeGoodsVo.getPickFreightCondition());
        feeRule.setPickupDay(storeGoodsVo.getFreePickupDay());
        freightRule.setFeeRule(feeRule);

        return freightRule;
    }

    public GoodsBaseData getGoodsBase(StoreGoodsVo info) {

        List<Integer> storeGoodsIdList = new ArrayList<>();
        storeGoodsIdList.add(info.getStoreGoodsId());
        List<StoreGoodsVo> storeGoodsVoList = agedmallStoreGoodsService.getStoreGoodsListByIds(storeGoodsIdList);

        List<Integer> chargeTemolateIdList = storeGoodsVoList.parallelStream().map(StoreGoodsVo::getLeaseChargeTemolateId).collect(Collectors.toList());
        List<AgedmallChargeTemplate> agedmallChargeTemplateList = agedmallChargeTemplateService.findByIds(chargeTemolateIdList);
        Map<Integer, List<AgedmallChargeTemplate>> chargeTemplateMap = agedmallChargeTemplateList.parallelStream().collect(Collectors.groupingBy(AgedmallChargeTemplate::getId));

        List<AgedmallHospitalSend> hospitalSends = agedmallHospitalSendService.getListByStoreGoodsIds(storeGoodsIdList);
        Map<Integer, List<AgedmallHospitalSend>> hospitalSendMap = new HashMap<>();
        hospitalSends.stream().forEach(hs -> {
            String storeIds = hs.getStoreIds();
            String[] storeIdArr = storeIds.split(",");
            Arrays.stream(storeIdArr).forEach(storeId -> {
                int sId = Integer.parseInt(storeId);
                List<AgedmallHospitalSend> hList = hospitalSendMap.get(sId);
                if (hList == null) {
                    hList = new ArrayList<>();
                    hospitalSendMap.put(sId, hList);
                }
                hList.add(hs);
            });
        });

        AgedmallStore store = agedmallStoreService.findStoreById(info.getStoreId());

        List<Integer> goodsIdList = storeGoodsVoList.parallelStream().map(StoreGoodsVo::getId).collect(Collectors.toList());
        List<AgedmallGoodsDeductionConf> goodsDeductionConfList = agedmallGoodsDeductionConfService.findDeductionListByGoodsIds(goodsIdList);
        Map<Integer, List<AgedmallGoodsDeductionConf>> goodsDeductionConfMap = goodsDeductionConfList.parallelStream().collect(Collectors.groupingBy(AgedmallGoodsDeductionConf::getGoodsId));

        return getGoodsBase(info, 1, chargeTemplateMap, hospitalSendMap, store, goodsDeductionConfMap);
    }

    public GoodsBaseData getGoodsBase(StoreGoodsVo info, Map<Integer, List<AgedmallChargeTemplate>> chargeTemplateMap, Map<Integer, List<AgedmallHospitalSend>> hospitalSendMap, AgedmallStore store, Map<Integer, List<AgedmallGoodsDeductionConf>> goodsDeductionConfMap) {
        return getGoodsBase(info, 1, chargeTemplateMap, hospitalSendMap, store, goodsDeductionConfMap);
    }

    public GoodsBaseData getGoodsBase(StoreGoodsVo info, int number, Map<Integer, List<AgedmallChargeTemplate>> chargeTemplateMap, Map<Integer, List<AgedmallHospitalSend>> hospitalSendMap, AgedmallStore store, Map<Integer, List<AgedmallGoodsDeductionConf>> goodsDeductionConfMap) {
        if (null == info) {
            return null;
        }
        // 租赁商品 商品价格为收费规格起始价
        if (GoodsConstant.GOODS_TYPE_LEASE.equals(info.getGoodsType())) {
            int chargeTemplateId = info.getLeaseChargeTemolateId();
            List<AgedmallChargeTemplate> chargeTemplateList = chargeTemplateMap.get(chargeTemplateId);
            AgedmallChargeTemplate agedmallChargeTemplate = chargeTemplateList != null && chargeTemplateList.size() > 0 ? chargeTemplateList.get(0) : null;

            if (null != agedmallChargeTemplate) {
                AgedmallChargeTemplateLeasePeriodExample leasePeriodExample=new AgedmallChargeTemplateLeasePeriodExample();
                leasePeriodExample.setOrderByClause("id ASC");
                leasePeriodExample.createCriteria().andDeletedEqualTo(false).andCustomTemplateIdEqualTo(agedmallChargeTemplate.getId());
                AgedmallChargeTemplateLeasePeriod agedmallChargeTemplateLeasePeriod = agedmallChargeTemplateLeasePeriodMapper.selectOneByExampleWithBLOBs(leasePeriodExample);
                if(agedmallChargeTemplateLeasePeriod!=null){
                    info.setSaleRetailPrice(agedmallChargeTemplateLeasePeriod.getBasePrice());
                }
            }
        }
        // 是否支持医院小时达
        List<AgedmallHospitalSend> hospitalSends = agedmallHospitalSendService.getByStoreAndGoods(info.getStoreId(), info.getId());
        info.setIsHospital(hospitalSends.size() > 0 ? 1 : 0);
        // 一个医院都没有 仅支持医院 改为否,这样可以支持普通配送
        if (hospitalSends.size() == 0) {
            info.setOnlyToHospital(0);
        }

        //商品基本信息 goods_base
        GoodsBaseData goodsBaseData = GoodsBaseData.getInstance(info);
        // 抵扣金
        BigDecimal deductNum = agedmallGoodsDeductionConfService.getDeductNumByGoodsByMap(info, goodsDeductionConfMap);
        if (null != deductNum) {
            goodsBaseData.setDeductNum(deductNum.multiply(new BigDecimal(number)).doubleValue());
        }
        List<GoodsVipSalesDto> salesDtoList = getvipSaleList(info.getId());
        goodsBaseData.setVipSales(salesDtoList);
        return goodsBaseData;
    }

    public List<GoodsVipSalesDto> getvipSaleList(Integer goodsId){
        List<GoodsVipSalesDto> productVipSales=new ArrayList<>();
        LitemallGoodsProductExample goodsProductExample=new LitemallGoodsProductExample();
        goodsProductExample.setOrderByClause("price ASC");
        goodsProductExample.createCriteria().andGoodsIdEqualTo(goodsId);
        LitemallGoodsProduct product = litemallGoodsProductMapper.selectOneByExampleSelective(goodsProductExample);
        if(ObjectUtil.isNotNull(product)&&StringUtils.isNotBlank(product.getVipJson())){
           productVipSales = getProductVipSales(product.getVipJson());
        }

        return productVipSales;
    }


    public List<GoodsVipSalesDto> getProductVipSales(String vipJson){
        List<GoodsVipSalesDto> salesDtoList=new ArrayList<>();
        if(StringUtils.isNotBlank(vipJson)){
           salesDtoList=GoodsVipSalesDto.getVipSalesList(vipJson);
        }
        return salesDtoList;
    }

    public GoodsDetailData getGoodsDetail(StoreGoodsVo info, Integer userId) {
        AgedmallGoodsSaleInfo agedmallGoodsSaleInfo = goodsSaleInfoService.getSaleInfoByGoodsId(info.getId());
        int saleCount = null == agedmallGoodsSaleInfo ? 0 : agedmallGoodsSaleInfo.getSaleCount();
        GoodsDetailData detailData = GoodsDetailData.getInstance(info, saleCount);
        // 说明设置
        AgedmallStore agedmallStore = agedmallStoreService.findStoreById(info.getStoreId().longValue());
        Integer type = GoodsConstant.GOODS_TYPE_SALE.equals(info.getGoodsType()) ? 1 : 0;
        AgedmallExplain agedmallExplain = agedmallExplainService.findByBusId(agedmallStore.getBusiId(), type);

        // 送货方式
        GoodsDetailDeliveryData delivery = new GoodsDetailDeliveryData();
        // 默认送货上门
        delivery.setIsDoor(1);
        delivery.setIsExpress(info.getCloudLock());
        List<AgedmallHospitalSend> hospitalSends = agedmallHospitalSendService.getByStoreAndGoods(info.getStoreId(), info.getId());
        delivery.setIsHospital(hospitalSends.size() > 0 ? 1 : 0);
        detailData.setDelivery(delivery);

        if (null != agedmallExplain) {
            delivery.setHtml(agedmallExplain.getDistributionModeContent());
            // 常见问题
            detailData.setQuestionHtml(agedmallExplain.getProblemContent());
            // 运费说明
            GoodsDetailFreightData rent = new GoodsDetailFreightData(agedmallExplain.getFreightContentShort(), agedmallExplain.getFreightContent());
            detailData.setFreight(rent);

            if (GoodsConstant.GOODS_TYPE_LEASE.equals(info.getGoodsType())) {
                // 租期说明
                GoodsDetailLeasetimeData time = new GoodsDetailLeasetimeData(agedmallExplain.getLeaseTimeContentShort(), agedmallExplain.getLeaseTimeContent());
                detailData.setLeasetime(time);
            } else {
                // 售卖说明
                detailData.setBuyHtml(agedmallExplain.getContent());
            }
        }

        // 是否收藏
        if (null == userId) {
            detailData.setIsCollect(0);
        } else {
            int isCollect = collectService.isCollect(userId, info.getStoreGoodsId(), CollectConstant.TYPE_GOODS);
            detailData.setIsCollect(isCollect);
        }

        // 推荐商品
        GoodsDetailFitGoodsData goodsDetailFitGoodsData = new GoodsDetailFitGoodsData();
        String recommendDesc = SystemConfig.getLitemallRecommendDesc();
        goodsDetailFitGoodsData.setDesc(recommendDesc);
        List<AgedmallGoodsGroupShip> recommendGoodsGroupShipList = agedmallGoodsGroupShipService.getByMainIdAndType(info.getId(), AgedmallGoodsGroupShipConstant.GROUP_TYPE_RECOMMEND);
        List<GoodsListData> recommandGoodsList = new ArrayList<>();
        for (AgedmallGoodsGroupShip agedmallGoodsGroupShip : recommendGoodsGroupShipList) {
            StoreGoodsVo goods = agedmallStoreGoodsService.getStoreGoodsByGoodsId(agedmallGoodsGroupShip.getGroupGoodsId(), info.getStoreId());
            // 该门店没有此推荐商品，不显示
            if (null == goods) {
                continue;
            }
            GoodsBaseData goodsBase = getGoodsBase(goods);
            GoodsListData goodsListData = new GoodsListData();
            try {
                BeanUtils.copyProperties(goodsListData, goodsBase);
            } catch (Exception e) {
                e.printStackTrace();
            }
            goodsListData.setChecked(agedmallGoodsGroupShip.getDefaultCheck() ? 1 : 0);
            goodsListData.setRequired(agedmallGoodsGroupShip.getRequiredBuy() ? 1 : 0);
            recommandGoodsList.add(goodsListData);
        }
        goodsDetailFitGoodsData.setGoodsList(recommandGoodsList);
        detailData.setFitGoods(goodsDetailFitGoodsData);

        // 组合商品
        GoodsDetailPackGoodsData goodsDetailPackGoodsData = new GoodsDetailPackGoodsData();
        String packageDesc = SystemConfig.getLitemallPackageDesc();
        goodsDetailPackGoodsData.setDesc(packageDesc);
        List<AgedmallGoodsGroupShip> packageGoodsGroupShipList = agedmallGoodsGroupShipService.getByMainIdAndType(info.getId(), AgedmallGoodsGroupShipConstant.GROUP_TYPE_PACKAGE);
        List<GoodsListData> packageGoodsList = new ArrayList<>();
        for (AgedmallGoodsGroupShip agedmallGoodsGroupShip : packageGoodsGroupShipList) {
            StoreGoodsVo goods = agedmallStoreGoodsService.getStoreGoodsByGoodsId(agedmallGoodsGroupShip.getGroupGoodsId(), info.getStoreId());
            GoodsBaseData goodsBase = getGoodsBase(goods);
            GoodsListData goodsListData = new GoodsListData();
            try {
                BeanUtils.copyProperties(goodsListData, goodsBase);
            } catch (Exception e) {
                e.printStackTrace();
            }
            goodsListData.setChecked(agedmallGoodsGroupShip.getDefaultCheck() ? 1 : 0);
            goodsListData.setRequired(agedmallGoodsGroupShip.getRequiredBuy() ? 1 : 0);
            packageGoodsList.add(goodsListData);
        }
        List<GoodsListData> saleGoodsList = packageGoodsList.stream().filter(p -> GoodsConstant.GOODS_TYPE_SALE.equals(p.getType())).collect(Collectors.toList());
        goodsDetailPackGoodsData.setSaleGoodsList(saleGoodsList);
        List<GoodsListData> leaseGoodsList = packageGoodsList.stream().filter(p -> GoodsConstant.GOODS_TYPE_LEASE.equals(p.getType())).collect(Collectors.toList());
        goodsDetailPackGoodsData.setLeaseGoodsList(leaseGoodsList);

        detailData.setPackGoods(goodsDetailPackGoodsData);

        // 商品规格参数列表数据
        List<LitemallGoodsAttribute> litemallGoodsAttributes = litemallGoodsAttributeService.queryByGid(info.getId());
        Map<String, List<LitemallGoodsAttribute>> attrMap = litemallGoodsAttributes.stream().collect(Collectors.toMap(
                LitemallGoodsAttribute::getGroup,
                p -> {
                    List<LitemallGoodsAttribute> carts = new ArrayList<>();
                    carts.add(p);
                    return carts;
                },
                (list1, list2) -> {
                    list1.addAll(list2);
                    return list1;
                }
        ));
        List<GoodsDetailParamsListData> params = new ArrayList<>();
        attrMap.forEach((k, v) -> {
            List<GoodsDetailParamsData> paramsData = v.stream().map(GoodsDetailParamsData::new).collect(Collectors.toList());
            GoodsDetailParamsListData paramsListData = new GoodsDetailParamsListData();
            paramsListData.setGroupName(k);
            paramsListData.setList(paramsData);
            params.add(paramsListData);
        });
        detailData.setParams(params);

        // 运费规则信息
        FreightRule freightRule = getFreightRule(info, agedmallStore);
        detailData.setFreightRule(freightRule);

        return detailData;
    }


    /**
     * 商品规格公用
     *
     * @return
     */
    @SuppressWarnings("all")
    private List<GoodsSpecDataInfo> getGoodsSpecDataInfo(Integer id, String type) {
        //商品自身属性SKU规格分类选项列表数据（选择多个SKU规格后，得到用户最终选择的SKU商品和价格信息）
        List<AgedmallGoodsSpecificationInfo> goodsSpecificationInfoList = agedmallGoodsSpecificationInfoService.getByGoodsIdAndType(id, type);
        List<GoodsSpecDataInfo> specList = goodsSpecificationInfoList.stream()
                .map(p -> {
                    List<LitemallGoodsSpecification> goodsSpecificationList = goodsSpecificationService.queryByParentId(p.getId());
                    List<GoodsSpecItemInfo> itemInfoList = goodsSpecificationList.stream().map(GoodsSpecItemInfo::getInstance).collect(Collectors.toList());
                    GoodsSpecDataInfo goodsSpecDataInfo = new GoodsSpecDataInfo();
                    goodsSpecDataInfo.setId(p.getId());
                    goodsSpecDataInfo.setName(p.getSpecName());
                    goodsSpecDataInfo.setDesc(p.getDesc());
                    goodsSpecDataInfo.setList(itemInfoList);
                    return goodsSpecDataInfo;
                }).collect(Collectors.toList());
        return specList;
    }

    /**
     * 商品规格公用
     *
     * @return
     */
    @SuppressWarnings("all")
    private List<GoodsSpecDataInfo> getGoodsSpecDataInfo(Integer id, String type, Map<String, List<AgedmallGoodsSpecificationInfo>> specificationMap, Map<Integer, List<LitemallGoodsSpecification>> goodsChildSpecificationMap) {
        //商品自身属性SKU规格分类选项列表数据（选择多个SKU规格后，得到用户最终选择的SKU商品和价格信息）
        String key = id + "#" + type;
        List<AgedmallGoodsSpecificationInfo> specificationList = specificationMap.get(key);
        List<AgedmallGoodsSpecificationInfo> goodsSpecificationInfoList = specificationList != null ? specificationList : new ArrayList<>();
        List<GoodsSpecDataInfo> specList = goodsSpecificationInfoList.stream()
                .map(p -> {
                    List<LitemallGoodsSpecification> gsList = goodsChildSpecificationMap.get(p.getId());
                    List<LitemallGoodsSpecification> goodsSpecificationList = gsList != null ? gsList : new ArrayList<>();
                    List<GoodsSpecItemInfo> itemInfoList = goodsSpecificationList.stream().map(GoodsSpecItemInfo::getInstance).collect(Collectors.toList());
                    GoodsSpecDataInfo goodsSpecDataInfo = new GoodsSpecDataInfo();
                    goodsSpecDataInfo.setId(p.getId());
                    goodsSpecDataInfo.setName(p.getSpecName());
                    goodsSpecDataInfo.setDesc(p.getDesc());
                    goodsSpecDataInfo.setList(itemInfoList);
                    return goodsSpecDataInfo;
                }).collect(Collectors.toList());
        return specList;
    }

    //商品已上架的SKU商品列表数据，即联动SKU规格分类最终选出来的商品是列表中的某个SKU商品，或未上架的SKU商品
    private List<GoodsSkuItemInfo> getSkuItemInfoList(StoreGoodsVo goods) {
        List<StoreGoodsProductVo> productList = agedmallStoreGoodsService.getStoreGoodsProductList(goods.getStoreId(), goods.getId(), GoodsProductConstant.TYPE_GOODS);

        AgedmallChargeTemplateLeasePeriod agedmallChargeTemplateLeasePeriod=null;
        // 租赁商品 商品价格为收费规格起始价
        if(goods.getLeaseChargeTemolateId()!=null){
            AgedmallChargeTemplateLeasePeriodExample leasePeriodExample=new AgedmallChargeTemplateLeasePeriodExample();
            leasePeriodExample.setOrderByClause("id ASC");
            leasePeriodExample.createCriteria().andDeletedEqualTo(false).andCustomTemplateIdEqualTo(goods.getLeaseChargeTemolateId());
            agedmallChargeTemplateLeasePeriod = agedmallChargeTemplateLeasePeriodMapper.selectOneByExampleWithBLOBs(leasePeriodExample);
        }



        boolean flag = GoodsConstant.GOODS_TYPE_LEASE.equals(goods.getGoodsType());
        AgedmallChargeTemplateLeasePeriod finalAgedmallChargeTemplateLeasePeriod = agedmallChargeTemplateLeasePeriod;
        List<GoodsSkuItemInfo> skuItemInfoList = productList.stream()
                .map(p -> {
                    if (flag && null != finalAgedmallChargeTemplateLeasePeriod) {
                        p.setSaleRetailPrice(finalAgedmallChargeTemplateLeasePeriod.getBasePrice());
                    }
                    List<GoodsVipSalesDto> productVipSales = getProductVipSales(p.getVipJson());
                    GoodsSkuItemInfo goodsSkuItemInfo = GoodsSkuItemInfo.getInstance(p, goods);
                    goodsSkuItemInfo.setStock(orderManager.getByStoreGoods(goods, p.getId()));
                    goodsSkuItemInfo.setVipSales(productVipSales);
                    return goodsSkuItemInfo;
                }).collect(Collectors.toList());
        return skuItemInfoList;
    }

    //商品已上架的SKU商品列表数据，即联动SKU规格分类最终选出来的商品是列表中的某个SKU商品，或未上架的SKU商品
    private List<GoodsSkuItemInfo> getSkuItemInfoList(StoreGoodsVo goods, Map<String, List<StoreGoodsProductVo>> storeGoodsProductStoreTypeKeyMap, Map<Integer, List<AgedmallChargeTemplate>> chargeTemplateMap,
                                                      Map<Long, List<AgedmallCloudGoodsProduct>> cloudGoodsProductMap) {
        String key = goods.getStoreId() + "#" + goods.getId() + "#" + GoodsProductConstant.TYPE_GOODS;
        List<StoreGoodsProductVo> pList = storeGoodsProductStoreTypeKeyMap.get(key);
        List<StoreGoodsProductVo> productList = pList != null ? pList : new ArrayList<>();

        // 租赁商品 商品价格为收费规格起始价
        List<AgedmallChargeTemplate> cList = chargeTemplateMap.get(goods.getLeaseChargeTemolateId());
        AgedmallChargeTemplate agedmallChargeTemplate = cList != null && cList.size() > 0 ? cList.get(0) : null;

        AgedmallChargeTemplateLeasePeriod agedmallChargeTemplateLeasePeriod=null;
        if(agedmallChargeTemplate!=null){
            AgedmallChargeTemplateLeasePeriodExample leasePeriodExample=new AgedmallChargeTemplateLeasePeriodExample();
            leasePeriodExample.setOrderByClause("id ASC");
            leasePeriodExample.createCriteria().andDeletedEqualTo(false).andCustomTemplateIdEqualTo(agedmallChargeTemplate.getId());
            agedmallChargeTemplateLeasePeriod = agedmallChargeTemplateLeasePeriodMapper.selectOneByExampleWithBLOBs(leasePeriodExample);
        }

        boolean flag = GoodsConstant.GOODS_TYPE_LEASE.equals(goods.getGoodsType());
        AgedmallChargeTemplateLeasePeriod finalAgedmallChargeTemplateLeasePeriod = agedmallChargeTemplateLeasePeriod;
        List<GoodsSkuItemInfo> skuItemInfoList = productList.stream()
                .map(p -> {
                    if (flag && null != finalAgedmallChargeTemplateLeasePeriod) {
                        p.setSaleRetailPrice(finalAgedmallChargeTemplateLeasePeriod.getBasePrice());
                    }
                    GoodsSkuItemInfo goodsSkuItemInfo = GoodsSkuItemInfo.getInstance(p, goods);
                    goodsSkuItemInfo.setStock(orderManager.getByStoreGoods(goods, p.getId(), cloudGoodsProductMap));
                    return goodsSkuItemInfo;
                }).collect(Collectors.toList());
        return skuItemInfoList;
    }

    //已上架的SKU服务列表数据，即联动SKU规格分类最终选出来的服务是列表中的某个SKU服务，或未上架的SKU服务
    private List<GoodsSkuItemInfo> getServiceSkuItemInfoList(Integer servieId) {
        Location location = LocationContext.get();
        if (location == null) {
            logger.error("获取sku服务列表数据时，未获取到用户的定位信息{}", servieId);
            return new ArrayList<>();
        }
        String city = location.getCity();
        List<ServiceProductVo> productList = litemallGoodsProductService.queryServiceProductById(servieId, city);

        List<GoodsSkuItemInfo> skuItemInfoList = productList.stream().map(GoodsSkuItemInfo::getInstance).collect(Collectors.toList());
        return skuItemInfoList;
    }

    private GoodsSkuItemInfo setItemInfo(org.linlinjava.litemall.db.domain.AgedmallGoodsOnlineService onlineService) {
        //根据关联表id查询对应的服务
        AgedmallOnlineService agedmallOnline
                = agedmallOnlineService.queryAgedmallOnLineId(onlineService.getOnlineSerivceProductId());
        //组装json格式
        GoodsSkuItemInfo itemInfo = new GoodsSkuItemInfo();
        itemInfo.setSkuId(agedmallOnline.getId());
        itemInfo.setImage(agedmallOnline.getServiceImage());
        //查询在线服务规格
        List<Integer> productIdList = agedmallOnlineServiceProductService.queryOnLineServiceProductGroupId(onlineService.getId());
        itemInfo.setSpecIds(productIdList);

        GoodsSkuItemPriceInfo priceInfo = new GoodsSkuItemPriceInfo();
        priceInfo.setPrice(null == agedmallOnline.getCostPrice() ? null : agedmallOnline.getCostPrice().doubleValue());
        priceInfo.setLinePrice(agedmallOnline.getCostPrice().doubleValue());
        itemInfo.setPriceInfo(priceInfo);
        return itemInfo;
    }

    public GoodsSku getSkuItemList(StoreGoodsVo goods) {
        // 商品SKU信息 goods_sku
        GoodsSku goodsSku = new GoodsSku();
        //商品自身属性SKU规格分类选项列表数据（选择多个SKU规格后，得到用户最终选择的SKU商品和价格信息）
        List<GoodsSpecDataInfo> goodsSpecDataInfoList = getGoodsSpecDataInfo(goods.getId(), AgedmallGoodsSpecificationInfoConstant.TYPE_SPEC);
        goodsSku.setSpecList(goodsSpecDataInfoList);

        //商品已上架的SKU商品列表数据，即联动SKU规格分类最终选出来的商品是列表中的某个SKU商品，或未上架的SKU商品
        List<GoodsSkuItemInfo> skuItemInfoList = getSkuItemInfoList(goods);
        goodsSku.setSkuList(skuItemInfoList);


        // 商品租金预算时长选择，租赁商品才有该字段
        GoodsSkuTimeSpecInfo timeSpec = null;
        AgedmallGoodsSpecificationInfo agedmallGoodsSpecificationInfo = agedmallGoodsSpecificationInfoService.getOneByGoodsIdAndType(goods.getId(), AgedmallGoodsSpecificationInfoConstant.TYPE_TIME);
        if (null != agedmallGoodsSpecificationInfo) {
            List<LitemallGoodsSpecification> goodsSpecificationList = goodsSpecificationService.queryByParentId(agedmallGoodsSpecificationInfo.getId());
            timeSpec = GoodsSkuTimeSpecInfo.getInstance(agedmallGoodsSpecificationInfo, goodsSpecificationList);
        } else {
            timeSpec = new GoodsSkuTimeSpecInfo();
        }
        goodsSku.setTimeSpec(timeSpec);

        // 商品定制服务SKU规格分类选项列表数据，例如：必选配件、更换配件、增加配件、都应该定义在该SKU分类中
        List<AgedmallGoodsSpecificationInfo> customSpecList = agedmallGoodsSpecificationInfoService.getByGoodsIdAndType(goods.getId(), AgedmallGoodsSpecificationInfoConstant.TYPE_CUSTOM);
        List<GoodsCustomSpecInfo> customSpecInfoList = new ArrayList<>();
        for (AgedmallGoodsSpecificationInfo specificationInfo : customSpecList) {
            List<AgedmallPartsVo> agedmallPartsVos = goodsService.queryParts(specificationInfo.getId(), goods.getStoreId());
            if (CollectionUtils.isNotEmpty(agedmallPartsVos)) {
                List<GoodsCustomSpecItemInfo> specItemInfoList = new ArrayList<>();
                for (AgedmallPartsVo agedmallPartsVo : agedmallPartsVos) {
                    StoreGoodsVo storeGoodsVo = agedmallStoreGoodsService.getStoreGoodsById(agedmallPartsVo.getId());
                    Integer stockNum = orderManager.getByStoreGoods(storeGoodsVo, null);

                    GoodsSku partsGoodsSku = new GoodsSku();
                    List<GoodsSpecDataInfo> partsGoodsSpecDataInfoList = getGoodsSpecDataInfo(storeGoodsVo.getId(), AgedmallGoodsSpecificationInfoConstant.TYPE_SPEC);
                    partsGoodsSku.setSpecList(partsGoodsSpecDataInfoList);
                    List<GoodsSkuItemInfo> partsSkuItemInfoList = getSkuItemInfoList(storeGoodsVo);
                    partsGoodsSku.setSkuList(partsSkuItemInfoList);

                    GoodsCustomSpecItemInfo goodsCustomSpecItemInfo = GoodsCustomSpecItemInfo.getInstance(agedmallPartsVo, partsGoodsSku, stockNum);
                    specItemInfoList.add(goodsCustomSpecItemInfo);
                }
                GoodsCustomSpecInfo goodsCustomSpecInfo = GoodsCustomSpecInfo.getInstance(specificationInfo, specItemInfoList);
                customSpecInfoList.add(goodsCustomSpecInfo);
            }
        }
        goodsSku.setCustomSpec(customSpecInfoList);

        //增加商品服务信息 serviceSpec
        List<AgedmallGoodsSpecificationInfo> serviceSpecList = agedmallGoodsSpecificationInfoService.getByGoodsIdAndType(goods.getId(), AgedmallGoodsSpecificationInfoConstant.TYPE_ONINE);
        List<GoodsCustomSpecInfo> serviceSpecInfoList = new ArrayList<>();
        for (AgedmallGoodsSpecificationInfo specificationInfo : serviceSpecList) {
            List<AgedmallPartsVo> agedmallPartsVos = goodsService.queryServices(specificationInfo.getId());
            if (CollectionUtils.isNotEmpty(agedmallPartsVos)) {
                List<GoodsCustomSpecItemInfo> specItemInfoList = new ArrayList<>();
                for (AgedmallPartsVo agedmallPartsVo : agedmallPartsVos) {
                    // 服务图片取第一张
                    String urls = agedmallPartsVo.getUrl();
                    if (org.apache.commons.lang3.StringUtils.isNotEmpty(urls)) {
                        List<String> urlList = JSONObject.parseArray(urls, String.class);
                        agedmallPartsVo.setUrl(CollectionUtils.isNotEmpty(urlList) ? urlList.get(0) : null);
                    }

                    GoodsSku partsGoodsSku = new GoodsSku();
                    List<GoodsSpecDataInfo> partsGoodsSpecDataInfoList = getGoodsSpecDataInfo(agedmallPartsVo.getId(), AgedmallGoodsSpecificationInfoConstant.TYPE_ONINE);
                    partsGoodsSku.setSpecList(partsGoodsSpecDataInfoList);
                    List<GoodsSkuItemInfo> partsSkuItemInfoList = getServiceSkuItemInfoList(agedmallPartsVo.getId());


                    partsGoodsSku.setSkuList(partsSkuItemInfoList);
                    GoodsCustomSpecItemInfo goodsCustomSpecItemInfo = GoodsCustomSpecItemInfo.getInstance(agedmallPartsVo, partsGoodsSku, null);
                    specItemInfoList.add(goodsCustomSpecItemInfo);
                }
                GoodsCustomSpecInfo goodsCustomSpecInfo = GoodsCustomSpecInfo.getInstance(specificationInfo, specItemInfoList);
                serviceSpecInfoList.add(goodsCustomSpecInfo);
            }
        }
        goodsSku.setServiceSpec(serviceSpecInfoList);

        // 商品特色服务SKU规格分类选项列表数据，例如：上门服务、保修服务、医疗保修、都应该定义在该SKU分类中，可灵活增加额外的收费服务项目
        List<AgedmallGoodsSpecificationInfo> serverSpecList = agedmallGoodsSpecificationInfoService.getByGoodsIdAndType(goods.getId(), AgedmallGoodsSpecificationInfoConstant.TYPE_EXTEND);
        List<GoodsExtendSpecInfo> extendSpecInfos = serverSpecList.stream()
                .map(p -> {
                    List<LitemallGoodsProductVo> goodsProductList = litemallGoodsProductService.queryServiceBySpecInfoId(p.getId());
                    List<GoodsExtendSpecItemInfo> extendSpecItemInfoList = goodsProductList.stream().map(GoodsExtendSpecItemInfo::getInstance).collect(Collectors.toList());
                    return GoodsExtendSpecInfo.getInstance(p, extendSpecItemInfoList);
                }).collect(Collectors.toList());
        goodsSku.setExtendSpec(extendSpecInfos);

        return goodsSku;
    }

    public GoodsSku getSkuItemList(StoreGoodsVo goods, Map<String, List<AgedmallGoodsSpecificationInfo>> specificationMap, Map<String, List<AgedmallPartsVo>> agedmallPartsMap,
                                   Map<Integer, List<LitemallGoodsSpecification>> goodsChildSpecificationMap, Map<Integer, List<StoreGoodsVo>> storeGoodsVoMap, Map<Integer, List<AgedmallPartsVo>> servicePartsMap,
                                   Map<Long, List<AgedmallCloudGoodsProduct>> cloudGoodsProductMap, Map<String, List<StoreGoodsProductVo>> storeGoodsProductStoreTypeKeyMap,
                                   Map<Integer, List<AgedmallChargeTemplate>> chargeTemplateMap) {
        Integer goodsId = goods.getId();
        if(goodsId == null) {
            logger.error("获取skuItem的goodsId全为空");
            goodsId = 0;
        }
        // 商品SKU信息 goods_sku
        GoodsSku goodsSku = new GoodsSku();
        //商品自身属性SKU规格分类选项列表数据（选择多个SKU规格后，得到用户最终选择的SKU商品和价格信息）
        List<GoodsSpecDataInfo> goodsSpecDataInfoList = getGoodsSpecDataInfo(goodsId, AgedmallGoodsSpecificationInfoConstant.TYPE_SPEC, specificationMap, goodsChildSpecificationMap);
        goodsSku.setSpecList(goodsSpecDataInfoList);

        //商品已上架的SKU商品列表数据，即联动SKU规格分类最终选出来的商品是列表中的某个SKU商品，或未上架的SKU商品
        List<GoodsSkuItemInfo> skuItemInfoList = getSkuItemInfoList(goods, storeGoodsProductStoreTypeKeyMap, chargeTemplateMap, cloudGoodsProductMap);
        goodsSku.setSkuList(skuItemInfoList);


        // 商品租金预算时长选择，租赁商品才有该字段
        GoodsSkuTimeSpecInfo timeSpec = null;
        List<AgedmallGoodsSpecificationInfo> timeSpecList = specificationMap.get(goodsId + "#" + AgedmallGoodsSpecificationInfoConstant.TYPE_TIME);
        AgedmallGoodsSpecificationInfo agedmallGoodsSpecificationInfo = timeSpecList != null ? timeSpecList.get(0) : null;
        if (null != agedmallGoodsSpecificationInfo) {
            int parentId = agedmallGoodsSpecificationInfo.getId();
            List<LitemallGoodsSpecification> childSpecificationList = goodsChildSpecificationMap.get(parentId);
            List<LitemallGoodsSpecification> goodsSpecificationList = childSpecificationList != null ? childSpecificationList : new ArrayList<>();
            timeSpec = GoodsSkuTimeSpecInfo.getInstance(agedmallGoodsSpecificationInfo, goodsSpecificationList);
        } else {
            timeSpec = new GoodsSkuTimeSpecInfo();
        }
        goodsSku.setTimeSpec(timeSpec);

        List<AgedmallGoodsSpecificationInfo> cusSpecList = specificationMap.get(goodsId + "#" + AgedmallGoodsSpecificationInfoConstant.TYPE_CUSTOM);
        // 商品定制服务SKU规格分类选项列表数据，例如：必选配件、更换配件、增加配件、都应该定义在该SKU分类中
        List<AgedmallGoodsSpecificationInfo> customSpecList = cusSpecList != null ? cusSpecList : new ArrayList<>();
        List<GoodsCustomSpecInfo> customSpecInfoList = new ArrayList<>();
        for (AgedmallGoodsSpecificationInfo specificationInfo : customSpecList) {
            String partKey = specificationInfo.getId() + "#" + goods.getStoreId();
            List<AgedmallPartsVo> partsVoList = agedmallPartsMap.get(partKey);
            List<AgedmallPartsVo> agedmallPartsVos = partsVoList != null ? partsVoList : new ArrayList<>();
            if (CollectionUtils.isNotEmpty(agedmallPartsVos)) {
                List<GoodsCustomSpecItemInfo> specItemInfoList = new ArrayList<>();
                for (AgedmallPartsVo agedmallPartsVo : agedmallPartsVos) {
                    List<StoreGoodsVo> storeGoodsVoList = storeGoodsVoMap.get(agedmallPartsVo.getId());
                    StoreGoodsVo storeGoodsVo = storeGoodsVoList != null && storeGoodsVoList.size() > 0 ? storeGoodsVoList.get(0) : null;
                    if (storeGoodsVo == null) {
                        logger.debug("配件信息不存在:{}", partKey);
                        continue;
                    }
                    Integer stockNum = orderManager.getByStoreGoods(storeGoodsVo, null, cloudGoodsProductMap);

                    GoodsSku partsGoodsSku = new GoodsSku();
                    List<GoodsSpecDataInfo> partsGoodsSpecDataInfoList = getGoodsSpecDataInfo(storeGoodsVo.getId(), AgedmallGoodsSpecificationInfoConstant.TYPE_SPEC, specificationMap, goodsChildSpecificationMap);
                    partsGoodsSku.setSpecList(partsGoodsSpecDataInfoList);
                    List<GoodsSkuItemInfo> partsSkuItemInfoList = getSkuItemInfoList(storeGoodsVo, storeGoodsProductStoreTypeKeyMap, chargeTemplateMap, cloudGoodsProductMap);
                    partsGoodsSku.setSkuList(partsSkuItemInfoList);

                    GoodsCustomSpecItemInfo goodsCustomSpecItemInfo = GoodsCustomSpecItemInfo.getInstance(agedmallPartsVo, partsGoodsSku, stockNum);
                    specItemInfoList.add(goodsCustomSpecItemInfo);
                }
                GoodsCustomSpecInfo goodsCustomSpecInfo = GoodsCustomSpecInfo.getInstance(specificationInfo, specItemInfoList);
                customSpecInfoList.add(goodsCustomSpecInfo);
            }
        }
        goodsSku.setCustomSpec(customSpecInfoList);

        //增加商品服务信息 serviceSpec
        List<AgedmallGoodsSpecificationInfo> onlineSpecList = specificationMap.get(goodsId + "#" + AgedmallGoodsSpecificationInfoConstant.TYPE_ONINE);
        List<AgedmallGoodsSpecificationInfo> serviceSpecList = onlineSpecList != null ? onlineSpecList : new ArrayList<>();
        List<GoodsCustomSpecInfo> serviceSpecInfoList = new ArrayList<>();
        for (AgedmallGoodsSpecificationInfo specificationInfo : serviceSpecList) {
            List<AgedmallPartsVo> agedmallPartsVos = servicePartsMap.get(specificationInfo.getId());
            if (CollectionUtils.isNotEmpty(agedmallPartsVos)) {
                List<GoodsCustomSpecItemInfo> specItemInfoList = new ArrayList<>();
                for (AgedmallPartsVo agedmallPartsVo : agedmallPartsVos) {
                    // 服务图片取第一张
                    String urls = agedmallPartsVo.getUrl();
                    if (org.apache.commons.lang3.StringUtils.isNotEmpty(urls)) {
                        boolean isArr = urls.startsWith("[");
                        String url = "";
                        if (isArr) {
                            List<String> urlList = JSONObject.parseArray(urls, String.class);
                            url = CollectionUtils.isNotEmpty(urlList) ? urlList.get(0) : null;
                        } else {
                            url = urls;
                        }
                        agedmallPartsVo.setUrl(url);
                    }

                    GoodsSku partsGoodsSku = new GoodsSku();
                    List<GoodsSpecDataInfo> partsGoodsSpecDataInfoList = getGoodsSpecDataInfo(agedmallPartsVo.getId(), AgedmallGoodsSpecificationInfoConstant.TYPE_ONINE);
                    partsGoodsSku.setSpecList(partsGoodsSpecDataInfoList);
                    List<GoodsSkuItemInfo> partsSkuItemInfoList = getServiceSkuItemInfoList(agedmallPartsVo.getId());


                    partsGoodsSku.setSkuList(partsSkuItemInfoList);
                    GoodsCustomSpecItemInfo goodsCustomSpecItemInfo = GoodsCustomSpecItemInfo.getInstance(agedmallPartsVo, partsGoodsSku, null);
                    specItemInfoList.add(goodsCustomSpecItemInfo);
                }
                GoodsCustomSpecInfo goodsCustomSpecInfo = GoodsCustomSpecInfo.getInstance(specificationInfo, specItemInfoList);
                serviceSpecInfoList.add(goodsCustomSpecInfo);
            }
        }
        goodsSku.setServiceSpec(serviceSpecInfoList);

        // 商品特色服务SKU规格分类选项列表数据，例如：上门服务、保修服务、医疗保修、都应该定义在该SKU分类中，可灵活增加额外的收费服务项目
        List<AgedmallGoodsSpecificationInfo> extendSpecList = specificationMap.get(goodsId + "#" + AgedmallGoodsSpecificationInfoConstant.TYPE_EXTEND);
        List<AgedmallGoodsSpecificationInfo> serverSpecList = extendSpecList != null ? extendSpecList : new ArrayList<>();
        List<GoodsExtendSpecInfo> extendSpecInfos = serverSpecList.stream()
                .map(p -> {
                    List<LitemallGoodsProductVo> goodsProductList = litemallGoodsProductService.queryServiceBySpecInfoId(p.getId());
                    List<GoodsExtendSpecItemInfo> extendSpecItemInfoList = goodsProductList.stream().map(GoodsExtendSpecItemInfo::getInstance).collect(Collectors.toList());
                    return GoodsExtendSpecInfo.getInstance(p, extendSpecItemInfoList);
                }).collect(Collectors.toList());
        goodsSku.setExtendSpec(extendSpecInfos);

        return goodsSku;
    }


    public Map<Integer, LitemallCategory> getGoodsRootCategory(List<Integer> goodsCatIds) {
        if (goodsCatIds.size() == 0) {
            return new HashMap<>();
        }
        Map<Integer, LitemallCategory> categoryMap = new HashMap<>();
        List<LitemallCategory> rootCategoryList = categoryService.queryL0();
        Map<Integer, LitemallCategory> rootCategoryMap = new HashMap<>();
        rootCategoryList.stream().forEach(rc -> {
            int cId = rc.getId();
            rootCategoryMap.put(cId, rc);
        });
        List<LitemallCategory> categoryList = categoryService.queryL2ByIds(goodsCatIds);
        categoryList.stream().forEach(c -> {
            int cId = c.getId();
            int rootCid = c.getRootId();
            categoryMap.put(cId, rootCategoryMap.get(rootCid));
        });
        return categoryMap;
    }

    public BaseResult stockWarning(String id, String type) {
        // TODO 先保存通知 具体业务还未规划完成
        AgedmallReplenishNotice notice = new AgedmallReplenishNotice();
        notice.setType(ReplenishNoticeConstant.TYPE_PRODUCT);
        notice.setSkuType(type);
        notice.setSpecificationIds(id);
        notice.setTitle("补货");
        notice.setContent("补货");
        agedmallReplenishNoticeService.add(notice);

        return RespUtil.success();
    }

    public BigDecimal countRent(int storeGoodsId, String storeId, Long day,Long ruleId) {
        return orderCalcService.ladderCountRent(storeGoodsId, day,ruleId);
    }

    private BigDecimal cappedCountRent(String goodsId, String storeId, Integer day) {
        AgedmallLeaseRuleConf ruleConf = agedmallLeaseRuleConfService.getByStoreIdAndGoodsId(Integer.parseInt(storeId), Integer.parseInt(goodsId));
        if (null == ruleConf) {
            return BigDecimal.ZERO;
        }

        BigDecimal totalPrice = BigDecimal.ZERO;
        BigDecimal yearPrice = BigDecimal.ZERO;
        BigDecimal monthPrice = BigDecimal.ZERO;
        BigDecimal dayPrice = BigDecimal.ZERO;

        AgedmallLeaseRuleConfRuleInfo rule = JacksonUtil.gson.fromJson(ruleConf.getRuleInfo(), AgedmallLeaseRuleConfRuleInfo.class);
        // 小于最小天数 按最小天数算
        if (day < rule.getMinDays()) {
            day = rule.getMinDays();
        }
        // 如果配置了【年最大金额】，计算有几年，年总价=【年最大金额*年数】，day=剩余天数
        if (null != rule.getYearMax()) {
            // 天数有几年
            int year = day / AgedmallLeaseRuleConfRuleInfo.year;
            yearPrice = rule.getYearMax().multiply(BigDecimal.valueOf(year));
            day = day % AgedmallLeaseRuleConfRuleInfo.year;
        }
        // 如果配置了【月最大金额】，计算有几月，月总价=【月最大金额*月数】，day=剩余天数
        if (null != rule.getMonthMax()) {
            // 有几月
            int month = day / AgedmallLeaseRuleConfRuleInfo.month;
            monthPrice = rule.getMonthMax().multiply(BigDecimal.valueOf(month));
            day = day % AgedmallLeaseRuleConfRuleInfo.month;
        }
        // 日总价=天数*每天金额
        dayPrice = rule.getDay().multiply(BigDecimal.valueOf(day));

        // 如果配置了【月最大金额】，且日总价大于【月最大金额】，日总价=【月最大金额】
        if (null != rule.getMonthMax() && dayPrice.compareTo(rule.getMonthMax()) > 0) {
            dayPrice = rule.getMonthMax();
        }
        // 如果配置了【年最大金额】,且日总价和月总价大于【年最大金额】，月总价=【年最大金额】,日总价=0 即 日总价加月总价=【年最大金额】
        if (null != rule.getYearMax() && monthPrice.add(dayPrice).compareTo(rule.getYearMax()) > 0) {
            monthPrice = rule.getYearMax();
            dayPrice = BigDecimal.ZERO;
        }
        // 总价
        totalPrice = yearPrice.add(monthPrice).add(dayPrice);
        // 如果总价超出 最大金额，取最大金额
        if (totalPrice.compareTo(rule.getMaxFee()) > 0) {
            totalPrice = rule.getMaxFee();
        }
        return totalPrice;
    }

    public BaseResult createOrder(Integer userId, CreateOrderForm createOrderForm) {


        if (userId == null) {
            return RespUtil.unlogin();
        }
        LitemallAddress litemallAddress = addressService.query(userId, createOrderForm.getAddressId());
        if (null == litemallAddress) {
            return RespUtil.badArgumentValue();
        }
        List<SelectGoodsSkuInfo> selectGoodsSkuInfoList = new ArrayList<>();
        selectGoodsSkuInfoList.add(createOrderForm.getMainGoods());
        selectGoodsSkuInfoList.addAll(createOrderForm.getFitGoodsList());
        selectGoodsSkuInfoList.addAll(createOrderForm.getPackGoodsList());

        List<Integer> goodsIdList = selectGoodsSkuInfoList.stream().map(p -> p.getGoodsSpec().getId()).collect(Collectors.toList());
        List<StoreGoodsVo> goodsList = goodsService.queryByIdList(goodsIdList);
        List<String> cityList = goodsList.stream().filter(p -> GoodsConstant.GOODS_TYPE_LEASE.equals(p.getGoodsType()))
                .map(StoreGoodsVo::getCityName).distinct().collect(Collectors.toList());
        if (CollectionUtils.isNotEmpty(cityList) && cityList.size() > 1) {
            throw new BizException("存在非同城租赁商品");
        }
        Map<Integer, StoreGoodsVo> goodsMap = goodsList.stream().collect(Collectors.toMap(StoreGoodsVo::getStoreGoodsId, p -> p));

        // 每个租赁商品都是一个子订单，售卖商品同一个店铺的N个售卖商品为一个子订单
        List<List<SelectGoodsSkuInfo>> selectList = new ArrayList<>();
        // 临时存放 门店id，购物车
        Map<Integer, List<SelectGoodsSkuInfo>> storeMap = new HashMap<>();
        for (SelectGoodsSkuInfo selectGoodsSkuInfo : selectGoodsSkuInfoList) {
            StoreGoodsVo goods = goodsMap.get(selectGoodsSkuInfo.getGoodsSpec().getId());
            if (GoodsConstant.GOODS_TYPE_LEASE.equals(goods.getGoodsType())) {
                List<SelectGoodsSkuInfo> carts = new ArrayList<>();
                carts.add(selectGoodsSkuInfo);
                selectList.add(carts);
            }
            if (GoodsConstant.GOODS_TYPE_SALE.equals(goods.getGoodsType())) {
                if (storeMap.containsKey(goods.getStoreId())) {
                    List<SelectGoodsSkuInfo> carts = storeMap.get(goods.getStoreId());
                    carts.add(selectGoodsSkuInfo);
                } else {
                    List<SelectGoodsSkuInfo> carts = new ArrayList<>();
                    carts.add(selectGoodsSkuInfo);
                    storeMap.put(goods.getStoreId(), carts);
                }
            }
        }
        for (List<SelectGoodsSkuInfo> value : storeMap.values()) {
            selectList.add(value);
        }

        Map<String, Object> data = new HashMap<>();
        List<Map<String, Object>> tempSubOrderList = new ArrayList();
        // 临时服务订单列表
        List<Map<String, Object>> tempServiceOrderList = new ArrayList();
        // 失效商品列表
        List<SubOrderGoodsVo> invalidGoodsList = new ArrayList<>();
        List<StoreGoodsVo> storeGoodsVoList = new ArrayList<>();
        // 是否小时达
        AgedmallHospitalSend hospitalSend = null;
        if (createOrderForm.getIsHospitalUrgent().equals(1) && null != createOrderForm.getHosId()) {
            hospitalSend = agedmallHospitalSendService.getById(createOrderForm.getHosId());
        }
        // 是否含有租赁可使用抵扣金商品
        boolean hasDeductionGoods = false;
        // 服务商品编号
        int serviceGoodsNo = 0;
        for (List<SelectGoodsSkuInfo> selectGoodsSkuInfos : selectList) {
            Map<String, Object> tempSubOrderMap = new HashMap<>();
            // storeInfo
            StoreGoodsVo mainGoods = goodsMap.get(selectGoodsSkuInfos.get(0).getGoodsSpec().getId());
            AgedmallStore store = agedmallStoreService.findStoreById(mainGoods.getStoreId());
            Map<String, Object> map = new HashMap<>();
            map.put("id", store.getId());
            map.put("name", store.getStoreName());
            map.put("logo", store.getLogo());
            map.put("isSelf", store.getOwnOptFlg());
            tempSubOrderMap.put("storeInfo", map);
            // goodsList
            List<SubOrderGoodsVo> subOrderGoodsVos = new ArrayList<>();
            BigDecimal orderPrice = BigDecimal.ZERO;
            for (SelectGoodsSkuInfo selectGoodsSkuInfo : selectGoodsSkuInfos) {
                serviceGoodsNo++;
                GoodsSpecInfo goodsSpec = selectGoodsSkuInfo.getGoodsSpec();
                List<CustomSpecInfo> customSpec = selectGoodsSkuInfo.getCustomSpec();
                List<ExtendSpecInfo> extendSpec = selectGoodsSkuInfo.getExtendSpec();

                StoreGoodsVo litemallGoods = goodsMap.get(goodsSpec.getId());
                StoreGoodsProductVo goodsProduct = agedmallStoreGoodsService.getStoreGoodsProduct(litemallGoods.getStoreId(), litemallGoods.getId(), Integer.parseInt(goodsSpec.getSkuId()));
                litemallGoods.setSaleRetailPrice(goodsProduct.getSaleRetailPrice());

                boolean flag = GoodsConstant.GOODS_TYPE_LEASE.equals(litemallGoods.getGoodsType());
                SubOrderGoodsVo subOrderGoodsVo = new SubOrderGoodsVo();
                subOrderGoodsVo.setServiceGoodsNo(serviceGoodsNo);
                subOrderGoodsVo.setSaleUserId(createOrderForm.getSaleUserId());
                GoodsBaseData goodsBaseData = getGoodsBase(litemallGoods);
                subOrderGoodsVo.setGoodsBase(goodsBaseData);

                BigDecimal totalPrice = BigDecimal.ZERO;
                SkuInfo skuInfo = new SkuInfo();
                GoodsSku goodsSku = getSkuItemList(litemallGoods);
                skuInfo.setGoodsSku(goodsSku);

                SelectedSpecInfo selectedGoodsSpec = new SelectedSpecInfo();
                selectedGoodsSpec.setId(Integer.parseInt(goodsSpec.getSkuId()));
                selectedGoodsSpec.setStock(goodsSpec.getStock());
                skuInfo.setSelectedGoodsSpec(selectedGoodsSpec);
                GoodsVipSalesDto selectProductVipSale = cartManager.getSelectProductVipSale(goodsProduct.
                        getVipJson(),userId,goodsSpec.getStock(),litemallGoods.getVipPriceFlag());
                skuInfo.setSelectedSkuVipSale(selectProductVipSale);
                BigDecimal salePrice=ObjectUtil.isNotNull(selectProductVipSale)&&selectProductVipSale.getPrice()!=null?selectProductVipSale.getPrice():goodsProduct.getSaleRetailPrice();
                totalPrice = totalPrice.add(new BigDecimal(goodsSpec.getStock()).multiply(flag ? goodsProduct.getLeaseDeposit() : salePrice));

                // 必须配件 是否有库存
                boolean neededParts = true;
                // 必须配件 是否支持小时达医院
                boolean neededHosp = true;
                List<SelectedSpecInfo> selectedCustomSpecList = new ArrayList<>();
                if (CollectionUtils.isNotEmpty(customSpec)) {
                    for (CustomSpecInfo customSpecInfo : customSpec) {
                        AgedmallGoodsSpecificationInfo specificationInfo = agedmallGoodsSpecificationInfoService.getById(customSpecInfo.getId());
                        // 是否必选
                        boolean mustSelect = null != specificationInfo && specificationInfo.getMinSelCount() >= 1;
                        List<CustomSpecSelectedInfo> selected = customSpecInfo.getSelected();
                        for (CustomSpecSelectedInfo customSpecSelectedInfo : selected) {
//                            LitemallGoodsProduct product = productService.findById(Integer.parseInt(customSpecSelectedInfo.getSkuId()));
                            StoreGoodsVo storeGoodsVo = agedmallStoreGoodsService.getStoreGoodsById(customSpecSelectedInfo.getId());
                            StoreGoodsProductVo goodsProductVo = agedmallStoreGoodsService.getStoreGoodsProduct(litemallGoods.getStoreId(), storeGoodsVo.getId(), Integer.parseInt(customSpecSelectedInfo.getSkuId()));
                            // 查询库存和库存类型
                            StockTypeDto stockTypeDto = orderManager.getStockTypeByStoreGoods(storeGoodsVo, Integer.parseInt(customSpecSelectedInfo.getSkuId()),
                                    litemallAddress.getLng(), litemallAddress.getLat());
                            if (mustSelect && null == stockTypeDto) {
                                neededParts = false;
                            }
                            SelectedSpecInfo selectedSpecInfo = new SelectedSpecInfo();
                            selectedSpecInfo.setId(customSpecSelectedInfo.getId());
                            selectedSpecInfo.setSkuId(Integer.parseInt(customSpecSelectedInfo.getSkuId()));
                            selectedSpecInfo.setStock(goodsProductVo.getPartsNumber() == 1 ? 1 : goodsSpec.getStock());
                            if (null != stockTypeDto) {
                                selectedSpecInfo.setStockType(stockTypeDto.getStockType());
                                selectedSpecInfo.setCloudStockId(stockTypeDto.getCloudStockId());
                                selectedSpecInfo.setIsInvalid(0);
                            } else {
                                selectedSpecInfo.setIsInvalid(1);
                            }

                            // 查询医院小时达
                            if (null != hospitalSend) {
                                List<String> storeIds = Arrays.asList(hospitalSend.getStoreIds().split(","));
                                int type = hospitalSend.getGoodsType();
                                List<String> goodsIds = Arrays.asList(org.apache.commons.lang3.StringUtils.split(hospitalSend.getGoodsIds(), ","));
                                boolean supportHosp = storeIds.contains(storeGoodsVo.getStoreId() + "") && (type == 1 || goodsIds.contains(storeGoodsVo.getId() + ""));
                                if (mustSelect && !supportHosp) {
                                    neededHosp = false;
                                }
                                if (!supportHosp) {
                                    logger.debug("下单,医院小时达不支持配送，库存直接设置成无货 userId={}, id={}, skuId={}", userId, customSpecSelectedInfo.getId(), customSpecSelectedInfo.getSkuId());
                                    selectedSpecInfo.setIsInvalid(1);
                                }
                            }

                            selectedCustomSpecList.add(selectedSpecInfo);

                            AgedmallGoodsParts parts = agedmallGoodsPartsService.getByGoodsIdAndCustGoodsId(litemallGoods.getId(), storeGoodsVo.getId());
                            // 售卖商品 或是配件先付的租赁商品 订单价格加上配件价格
                            if (GoodsConstant.GOODS_TYPE_SALE.equals(litemallGoods.getGoodsType())
                                    || (null != parts && parts.getPayOrder().equals(0))) {
                                totalPrice = totalPrice.add(new BigDecimal(selectedSpecInfo.getStock()).multiply(goodsProductVo.getSaleRetailPrice()));
                            }
                        }
                    }
                }
                skuInfo.setSelectedCustomSpec(selectedCustomSpecList);

                // 特色服务
                List<SelectedSpecInfo> selectedExtendSpecList = new ArrayList<>();
                if (CollectionUtils.isNotEmpty(extendSpec)) {
                    for (ExtendSpecInfo extendSpecInfo : extendSpec) {
                        String[] selectedArr = extendSpecInfo.getSelected().split(",");
                        for (String s : selectedArr) {
                            LitemallGoodsProduct product = productService.findById(Integer.parseInt(s));
                            SelectedSpecInfo selectedSpecInfo = new SelectedSpecInfo();
                            selectedSpecInfo.setId(Integer.parseInt(s));
                            selectedSpecInfo.setStock(product.getPartsNumber() == 1 ? 1 : goodsSpec.getStock());
                            selectedExtendSpecList.add(selectedSpecInfo);

                            totalPrice = totalPrice.add(new BigDecimal(selectedSpecInfo.getStock()).multiply(product.getPrice()));
                        }
                    }
                }
                skuInfo.setSelectedExtendSpec(selectedExtendSpecList);

                subOrderGoodsVo.setSkuInfo(skuInfo);
                subOrderGoodsVo.setTotalPrice(totalPrice.doubleValue());
                subOrderGoodsVo.setGoodsLease(new GoodsLease(litemallGoods.getCreditLease(), WxPayScoreConfig.MIN_SCORE));

                // 商品是否有效
                if (goodsBaseData.getIsOffline() == 1) {
                    invalidGoodsList.add(subOrderGoodsVo);
                    continue;
                }
                // 必须配件是否有库存
                if (!neededParts) {
                    invalidGoodsList.add(subOrderGoodsVo);
                    continue;
                }
                // 必须配件是否支持医院小时达
                if (!neededHosp) {
                    invalidGoodsList.add(subOrderGoodsVo);
                    continue;
                }
                // 查询医院小时达
                if (null != hospitalSend) {
                    List<String> storeIds = Arrays.asList(hospitalSend.getStoreIds().split(","));
                    int type = hospitalSend.getGoodsType();
                    List<String> goodsIds = Arrays.asList(org.apache.commons.lang3.StringUtils.split(hospitalSend.getGoodsIds(), ","));
                    boolean supportHosp = storeIds.contains(litemallGoods.getStoreId() + "") && (type == 1 || goodsIds.contains(litemallGoods.getId() + ""));
                    if (!supportHosp) {
                        invalidGoodsList.add(subOrderGoodsVo);
                        continue;
                    }
                }

                StoreGoodsVo storeGoodsVo = goodsMap.get(goodsSpec.getId());
                storeGoodsVo.setStock(goodsSpec.getStock());
                // 查询库存和库存类型
                StockTypeDto stockTypeDto = orderManager.getStockTypeByStoreGoods(storeGoodsVo, Integer.parseInt(goodsSpec.getSkuId()),
                        litemallAddress.getLng(), litemallAddress.getLat());
                // 没有库存
                if (null == stockTypeDto) {
                    invalidGoodsList.add(subOrderGoodsVo);
                    continue;
                }
                subOrderGoodsVo.setStockType(stockTypeDto.getStockType());
                subOrderGoodsVo.setCloudStockId(stockTypeDto.getCloudStockId());
                subOrderGoodsVo.setRuleId(goodsSpec.getRuleId());
                storeGoodsVo.setStockType(stockTypeDto.getStockType());
                storeGoodsVo.setCloudStockId(stockTypeDto.getCloudStockId());

                // 超出范围
                boolean isDelivery = orderManager.isDelivery(storeGoodsVo, litemallAddress, InventoryUtil.STOCK_CLOUD.equals(stockTypeDto.getStockType()),stockTypeDto.getCloudStockId());
                if (isDelivery) {
                    invalidGoodsList.add(subOrderGoodsVo);
                    continue;

                }

                // 在线服务,,,在线服务要放在商品库存和配送范围判断之后，因为没有商品 服务也就不能下单了
                List<CustomSpecInfo> serviceSpecInfos = selectGoodsSkuInfo.getServiceSpec();
                if (CollectionUtils.isNotEmpty(serviceSpecInfos)) {
                    for (CustomSpecInfo serviceSpecInfo : serviceSpecInfos) {
                        List<CustomSpecSelectedInfo> selected = serviceSpecInfo.getSelected();
                        for (CustomSpecSelectedInfo serviceSpecSelectedInfo : selected) {
                            JSONObject tempServiceOrder = new JSONObject();

                            AgedmallOnlineService onlineService = agedmallOnlinesService.queryAgedmallOnLineId(serviceSpecSelectedInfo.getId());
                            String city = litemallAddress.getCity();
                            ServiceProductVo product = litemallGoodsProductService.findServiceById(Integer.parseInt(serviceSpecSelectedInfo.getSkuId()), city);

                            SubOrderGoodsVo serviceInfo = new SubOrderGoodsVo();
                            serviceInfo.setServiceGoodsNo(serviceGoodsNo);
                            GoodsBaseData serviceBaseData = getServiceBaseData(onlineService, product);
                            serviceInfo.setGoodsBase(serviceBaseData);

                            SkuInfo serviceSkuInfo = new SkuInfo();
                            GoodsSku serviceSku = getServiceSku(onlineService);
                            serviceSkuInfo.setGoodsSku(serviceSku);

                            SelectedSpecInfo selectedServiceSpec = new SelectedSpecInfo();
                            selectedServiceSpec.setId(Integer.parseInt(serviceSpecSelectedInfo.getSkuId()));
                            // 服务默认1次
                            selectedServiceSpec.setStock(1);
                            serviceSkuInfo.setSelectedGoodsSpec(selectedServiceSpec);

                            serviceInfo.setSkuInfo(serviceSkuInfo);
                            serviceInfo.setGoodsId(litemallGoods.getId());
                            serviceInfo.setStoreGoodsId(litemallGoods.getStoreGoodsId());

                            // 服务不支持当前城市
                            if (null == product.getCityProductPrice()) {
                                invalidGoodsList.add(serviceInfo);
                                continue;
                            }

                            tempServiceOrder.put("goodsInfo", serviceInfo);
                            tempServiceOrder.put("extends", getServiceExtends(onlineService, litemallAddress.getCity()));
//                            BigDecimal price = null != product.getCityProductPrice() ? product.getCityProductPrice() : product.getPrice();
                            tempServiceOrder.put("totalPrice", product.getCityProductPrice());

                            AgedmallGoodsOnlineServiceExample goodsOnlineServiceExample = new AgedmallGoodsOnlineServiceExample();
                            goodsOnlineServiceExample.or().andDeletedEqualTo(false)
                                    .andGoodsIdEqualTo(litemallGoods.getId())
                                    .andOnlineSerivceProductIdEqualTo(onlineService.getId());
                            org.linlinjava.litemall.db.domain.AgedmallGoodsOnlineService goodsOnlineService = agedmallGoodsOnlineServiceMapper.selectOneByExample(goodsOnlineServiceExample);
                            tempServiceOrder.put("isPrepaid", GoodsConstant.GOODS_TYPE_LEASE.equals(litemallGoods.getGoodsType()) ? goodsOnlineService.getPayOrder() : 0);

                            tempServiceOrderList.add(tempServiceOrder);
                        }
                    }
                }

                subOrderGoodsVos.add(subOrderGoodsVo);
                orderPrice = orderPrice.add(totalPrice);
                storeGoodsVoList.add(storeGoodsVo);

                // 判断是否有抵扣金
                if (goodsBaseData.getDeductNum() > 0) {
                    hasDeductionGoods = true;
                }
            }
            tempSubOrderMap.put("goodsList", subOrderGoodsVos);

            if (CollectionUtils.isNotEmpty(storeGoodsVoList)) {
                List<StoreGoodsProductVo> storeGoodsProductVoList=new ArrayList<>();
                StoreGoodsProductVo goodsProductVo = agedmallStoreGoodsService.getStoreGoodsProduct(storeGoodsVoList.get(0).getStoreId()
                        , storeGoodsVoList.get(0).getId(),Integer.parseInt(createOrderForm.getMainGoods().getGoodsSpec().getSkuId()));
                storeGoodsProductVoList.add(goodsProductVo);


                List<ChannelGoodsBindDto> bindDtoList=new ArrayList<>();
                    ChannelGoodsBindDto goodsBindDto=new ChannelGoodsBindDto();
                    goodsBindDto.setHosLinkCode(createOrderForm.getHosLinkCode());//二维码code
                    goodsBindDto.setGoodsId(createOrderForm.getMainGoods().getGoodsSpec().getId().longValue());//门店商品id
                    goodsBindDto.setChannel(createOrderForm.getChannel());//分成渠道
                    goodsBindDto.setSaleUserId(createOrderForm.getSaleUserId());
                    bindDtoList.add(goodsBindDto);

                // extends
                Map<String, Object> extendsMap = orderManager.getExtends(storeGoodsVoList, litemallAddress, hospitalSend,
                        createOrderForm.getChannel(),createOrderForm.getHosLinkCode(),storeGoodsProductVoList);
                extendsMap.put("province", store.getProvinceName());
                extendsMap.put("city", store.getCityName());
                tempSubOrderMap.put("extends", extendsMap);
                tempSubOrderMap.put("channelGoodsBind", bindDtoList);
                // 单个租赁商品 运费是先付还是后付
                if (1 == storeGoodsVoList.size()) {
                    StoreGoodsVo storeGoods = storeGoodsVoList.get(0);
                    if (GoodsConstant.GOODS_TYPE_LEASE.equals(storeGoods.getGoodsType())) {
                        tempSubOrderMap.put("isPrepaid", storeGoods.getPayOrder());
                    }
                }
                // totalPrice
                tempSubOrderMap.put("totalPrice", orderPrice);
                // 是否在配送范围
//                int isOutRange = null == extendsMap.get("isOutRange") ? 0 : (int)extendsMap.get("isOutRange");
//                tempSubOrderMap.put("isOutRange", isOutRange);
                tempSubOrderList.add(tempSubOrderMap);
            }
        }
        data.put("tempSubOrderList", tempSubOrderList);
        data.put("tempServiceOrderList", tempServiceOrderList);
        data.put("invalidGoodsList", invalidGoodsList);

        // 订单说明信息
        List<ExplainDto> explainDtos = goodsList.stream()
                .map(p -> new ExplainDto(GoodsConstant.GOODS_TYPE_SALE.equals(p.getGoodsType()) ? 1 : 0, p.getStoreId())).distinct().collect(Collectors.toList());
        data.put("readmeList", orderManager.getReadmeList(explainDtos));
        // 信用租最大金额
        data.put("creditLeaseMaxPrice", new BigDecimal(SystemConfig.getLitemallCreditLeaseMaxPrice()));
        // 是否可使用抵扣金(有抵扣金，且有租赁商品可使用抵扣金)
        AgedmallUserInfo agedmallUserInfo = agedmallUserInfoService.getByUid(userId);
        int canUseDeduct = 0;
        if (ObjectUtil.isNotNull(agedmallUserInfo)) {
            canUseDeduct = (agedmallUserInfo.getDeductAmount().compareTo(BigDecimal.ZERO) > 0 && hasDeductionGoods) ? 1 : 0;
            logger.info("获取用户抵扣金:{},{}", userId, canUseDeduct);
        }
        data.put("canUseDeduct", canUseDeduct);
        return RespUtil.success(data);
    }

    public BaseResult getHospitalList(Integer userId, CreateOrderForm createOrderForm) {
        if (userId == null) {
            return RespUtil.unlogin();
        }

        List<SelectGoodsSkuInfo> selectGoodsSkuInfoList = new ArrayList<>();
        selectGoodsSkuInfoList.add(createOrderForm.getMainGoods());
        if (createOrderForm.getFitGoodsList() != null) {
            selectGoodsSkuInfoList.addAll(createOrderForm.getFitGoodsList());
        }
        if (createOrderForm.getPackGoodsList() != null) {
            selectGoodsSkuInfoList.addAll(createOrderForm.getPackGoodsList());
        }
        List<Integer> goodsIdList = selectGoodsSkuInfoList.stream().map(p -> p.getGoodsSpec().getId()).collect(Collectors.toList());
        List<StoreGoodsVo> goodsList = goodsService.queryByIdList(goodsIdList);
        List<AgedmallHospitalSend> agedmallHospitalSends = new ArrayList<>();
        for (StoreGoodsVo storeGoodsVo : goodsList) {
            List<AgedmallHospitalSend> hospitalSends = agedmallHospitalSendService.getByStoreAndGoods(storeGoodsVo.getStoreId(), storeGoodsVo.getId());
            agedmallHospitalSends.addAll(hospitalSends);
        }

        List<GoodsHospitalInfo> hospitalInfos = agedmallHospitalSends.stream().distinct().map(GoodsHospitalInfo::new).collect(Collectors.toList());

        return RespUtil.success(hospitalInfos);
    }

    public BaseResult saleReadme(Integer goodsId){
        String readmeHtml = appGoodsMapper.getBusiIdByGoodsId(goodsId);
        Map<String, String> map=new HashMap<>();
        map.put("readmeHtml",readmeHtml);
        return RespUtil.success(map);
    }

    /**
     * 获取地区该商品最近门店且有库存的门店商品
     *
     * @return
     */
    public List<StoreGoodsVo> getNearestStoreGoodsList(List<Integer> goodsIdList, BigDecimal lng, BigDecimal lat, String city, List<Integer> hospitalStoreList) {
        List<StoreGoodsVo> result = new ArrayList<>();
        for (Integer goodsId : goodsIdList) {
            StoreGoodsVo goodsVo = null;
            // 门店商品 按距离排序
            List<StoreGoodsVo> initialStoreGoodsVos = agedmallStoreGoodsService.getStoreGoodsByGoodsIdAndLngLat(goodsId, lng, lat, city, hospitalStoreList != null && hospitalStoreList.size() > 0 ? hospitalStoreList : null);
            //去除已经被删除的门店商品
            List<StoreGoodsVo> storeGoodsVos=new ArrayList<>();
            for (int i = 0; i <initialStoreGoodsVos.size() ; i++) {
                if(!initialStoreGoodsVos.get(i).getStoreGoodsDeleted()){
                    storeGoodsVos.add(initialStoreGoodsVos.get(i));
                }
            }
            for (StoreGoodsVo storeGoodsVo : storeGoodsVos) {
                if (orderManager.getByStoreGoods(storeGoodsVo, null) > 0) {
                    goodsVo = storeGoodsVo;
                    break;
                }
            }
            // 都没有库存 取第一个
            if (null == goodsVo && CollectionUtils.isNotEmpty(storeGoodsVos)) {
                goodsVo = storeGoodsVos.get(0);
            }
            if (null != goodsVo) {
                // 租赁商品 商品价格为收费规格起始价
                if (GoodsConstant.GOODS_TYPE_LEASE.equals(goodsVo.getGoodsType())) {
                    AgedmallChargeTemplateLeasePeriodExample leasePeriodExample=new AgedmallChargeTemplateLeasePeriodExample();
                    leasePeriodExample.setOrderByClause("id ASC");
                    leasePeriodExample.createCriteria().andDeletedEqualTo(false).andCustomTemplateIdEqualTo(goodsVo.getLeaseChargeTemolateId());
                    AgedmallChargeTemplateLeasePeriod agedmallChargeTemplateLeasePeriod = agedmallChargeTemplateLeasePeriodMapper.selectOneByExampleWithBLOBs(leasePeriodExample);


                    if (null != agedmallChargeTemplateLeasePeriod) {
                        goodsVo.setSaleRetailPrice(agedmallChargeTemplateLeasePeriod.getBasePrice());
                    }
                }
                result.add(goodsVo);
            }
        }
        return result;
    }

    // 获取某规格服务的基础数据
    public GoodsBaseData getServiceBaseData(AgedmallOnlineService onlineService, ServiceProductVo product) {
        GoodsBaseData goodsBaseData = GoodsBaseData.getInstance(onlineService, product);
        String tags = onlineService.getTagId();
        if (org.apache.commons.lang3.StringUtils.isNotBlank(tags)) {
            List<String> tagIds = Arrays.asList(tags.split(","));
            List<Long> lTagIds = tagIds.stream().map(Long::parseLong).collect(Collectors.toList());
            AgedmallTagsExample example = new AgedmallTagsExample();
            example.createCriteria().andIdIn(lTagIds);
            List<AgedmallTags> agedmallTags = agedmallTagsMapper.selectByExample(example);
            List<GoodsTag> goodsTags = agedmallTags.stream()
                    .map(p -> {
                        GoodsTag tag = new GoodsTag();
                        tag.setTag(p.getName());
                        tag.setIsRed(p.getProminent());
                        return tag;
                    }).collect(Collectors.toList());
            goodsBaseData.setTags(goodsTags);
        }
        return goodsBaseData;
    }

    // 获取服务的sku
    public GoodsSku getServiceSku(AgedmallOnlineService onlineService) {
        // 服务SKU信息
        GoodsSku goodsSku = new GoodsSku();
        //服务自身属性SKU规格分类选项列表数据（选择多个SKU规格后，得到用户最终选择的SKU服务和价格信息）
        List<GoodsSpecDataInfo> goodsSpecDataInfoList = getGoodsSpecDataInfo(onlineService.getId(), AgedmallGoodsSpecificationInfoConstant.TYPE_ONINE);
        goodsSku.setSpecList(goodsSpecDataInfoList);

        //服务已上架的SKU列表数据，即联动SKU规格分类最终选出来的服务是列表中的某个SKU服务，或未上架的SKU服务
        List<GoodsSkuItemInfo> skuItemInfoList = getServiceSkuItemInfoList(onlineService.getId());
        goodsSku.setSkuList(skuItemInfoList);

        return goodsSku;
    }

    // 获取在线服务的扩展数据
    public ServiceExtends getServiceExtends(AgedmallOnlineService onlineService, String city) {
        Integer cityId = litemallRegionService.getCityIdByName(city);
        ServiceExtends serviceExtends = new ServiceExtends();

        if (org.apache.commons.lang3.StringUtils.isNotEmpty(onlineService.getServiceDepartment())) {
            List<String> departmentIds = Arrays.asList(onlineService.getServiceDepartment().split(","));
            List<Integer> departmentIdList = departmentIds.stream().map(Integer::parseInt).collect(Collectors.toList());
            AgedmallDepartmentExample departmentExample = new AgedmallDepartmentExample();
            departmentExample.createCriteria().andDeletedEqualTo(false)
                    .andIdIn(departmentIdList);
            List<AgedmallDepartment> agedmallDepartments = agedmallDepartmentMapper.selectByExample(departmentExample);
            List<ServiceExtendsDepartment> departmentList = new ArrayList<>();
            for (AgedmallDepartment agedmallDepartment : agedmallDepartments) {
                ServiceExtendsDepartment extendsDepartment = new ServiceExtendsDepartment();
                extendsDepartment.setDepId(agedmallDepartment.getId());
                extendsDepartment.setDepName(agedmallDepartment.getName());

                List<ServiceExtendsDoctor> agedmallDoctorInfos = agedmallOnlineMapper.selectByDepartmentAndCity(agedmallDepartment.getId(), cityId);
                extendsDepartment.setDoctorList(agedmallDoctorInfos);
                departmentList.add(extendsDepartment);
            }
            serviceExtends.setDepartmentList(departmentList);
        }

        ServiceExtendsSubtime subtime = new ServiceExtendsSubtime();
        subtime.setMaxDay(onlineService.getAppointmentDay());
        List<ServiceTime> serviceTimes = JSONObject.parseArray(onlineService.getServiceTime(), ServiceTime.class);
        List<ServiceExtendsTime> timeList = serviceTimes.stream().map(ServiceExtendsTime::new).collect(Collectors.toList());
        subtime.setTimeList(timeList);
        serviceExtends.setSubtime(subtime);

        return serviceExtends;
    }


    public BaseResult weixinSubGoodsArrived(Integer userId,WeixinSubGoodsArrivedForm weixinSubGoodsArrivedForm){
        LitemallUser user=litemallUserMapper.selectByPrimaryKey(userId);
        AgedmallSubscribeToInformExample subscribeToInformExample=new AgedmallSubscribeToInformExample();
        subscribeToInformExample.createCriteria().andUserOpenIdEqualTo(user.getWeixinOpenid()==null?user.getUsername():user.getWeixinOpenid()).
                andGoodsIdEqualTo(weixinSubGoodsArrivedForm.getGoodsId()).
                andSkuIdEqualTo(weixinSubGoodsArrivedForm.getSkuId()).andSendFlagEqualTo(0);
        AgedmallSubscribeToInform existSubscribe = agedmallSubscribeToInformMapper.selectOneByExample(subscribeToInformExample);
        if(ObjectUtil.isNull(existSubscribe)){
            AgedmallSubscribeToInform subscribe=WeixinSubGoodsArrivedForm.toSubscribeToInform(weixinSubGoodsArrivedForm);
            subscribe.setUserOpenId(user.getWeixinOpenid()==null?user.getUsername():user.getWeixinOpenid());
            StoreGoodsVo storeGoodsVo=agedmallStoreGoodsService.getStoreGoodsById(weixinSubGoodsArrivedForm.getGoodsId().intValue());
            LitemallGoodsProduct goodsProduct = litemallGoodsProductService.findById(weixinSubGoodsArrivedForm.getSkuId().intValue());
            Map<String, Object> objectMap=new HashMap<>();
            Map<String, Object> goodsNameValue=new HashMap<>();
            goodsNameValue.put("value",storeGoodsVo.getName());
            Map<String, Object> goodsAmountValue=new HashMap<>();
            goodsAmountValue.put("value",storeGoodsVo.getSaleRetailPrice()==null||storeGoodsVo.getSaleRetailPrice().compareTo(BigDecimal.ZERO)==0?
                    storeGoodsVo.getDeposit():storeGoodsVo.getSaleRetailPrice());
            Map<String, Object> promptValue=new HashMap<>();
            promptValue.put("value","快点击下方详情进入抢购～");
            objectMap.put("thing1",goodsNameValue);
            objectMap.put("amount2",goodsAmountValue);
            objectMap.put("thing3",promptValue);
            subscribe.setTemplateData(JSON.toJSONString(objectMap));
            agedmallSubscribeToInformMapper.insertSelective(subscribe);
        }
        return   RespUtil.success();
    }


    public BaseResult freightForecast(FreightForecastForm freightForecastForm){
        Map<String, Object> map=new HashMap<>();
        // 门店商品信息
        StoreGoodsVo info = agedmallStoreGoodsService.getStoreGoodsById(freightForecastForm.getGoodsId());
        if (info == null) {
            return RespUtil.badArgumentValue();
        }
        AgedmallStore store=agedmallStoreService.findStoreById(info.getStoreId().longValue());
        List<StoreGoodsProductVo> storeGoodsProductVoList=new ArrayList<>();
        StoreGoodsProductVo goodsProductVo = agedmallStoreGoodsService.getStoreGoodsProduct(info.getStoreId(), info.getId(),freightForecastForm.getSkuId());
        storeGoodsProductVoList.add(goodsProductVo);
        LitemallAddress address=new LitemallAddress();
        LitemallRegionExample regionExample=new LitemallRegionExample();
        regionExample.createCriteria().andTypeEqualTo((byte)1).andNameEqualTo(freightForecastForm.getProvince());
        LitemallRegion litemallRegions = litemallRegionMapper.selectOneByExample(regionExample);
        address.setLng(freightForecastForm.getLng());
        address.setLat(freightForecastForm.getLat());
        address.setProvinceId(litemallRegions.getId());
        //云仓判断范围使用;
        Integer provinceId=litemallRegions.getId();
        // 查询库存和库存类型
        StockTypeDto stockTypeDto = orderManager.getStockTypeByStoreGoods(info, freightForecastForm.getSkuId(),
                freightForecastForm.getLng(), freightForecastForm.getLat());
        // 没有库存
        if (null == stockTypeDto) {
            map.put("isCalcSuccess",0);
            map.put("calcErrorMsg","当前商品没有库存");
           return RespUtil.success(map);
        }
        info.setStockType(stockTypeDto.getStockType());
        info.setCloudStockId(stockTypeDto.getCloudStockId());

        // 超出范围
        boolean delivery = orderManager.isDelivery(info, address,InventoryUtil.STOCK_CLOUD.equals(stockTypeDto.getStockType())
                , stockTypeDto.getCloudStockId());
        if (delivery) {
            map.put("isCalcSuccess",0);
            map.put("calcErrorMsg","超出配送范围");
            return RespUtil.success(map);
        }

        //判断完成开始计算运费

        AgedmallHospitalSend hospitalSend = null;
        if ( null != freightForecastForm.getHosId()) {
            hospitalSend = agedmallHospitalSendService.getById(freightForecastForm.getHosId());
        }

        if (null != hospitalSend) {
            List<String> storeIds = Arrays.asList(hospitalSend.getStoreIds().split(","));
            int type = hospitalSend.getGoodsType();
            List<String> goodsIds = Arrays.asList(org.apache.commons.lang3.StringUtils.split(hospitalSend.getGoodsIds(), ","));
            boolean supportHosp = storeIds.contains(info.getStoreId() + "") && (type == 1 || goodsIds.contains(info.getId() + ""));
            if (!supportHosp) {
                map.put("isCalcSuccess",0);
                map.put("calcErrorMsg","医院不支持配送当前商品");
                return RespUtil.success(map);
            }
        }

        List<StoreGoodsVo> storeGoodsVoList=new ArrayList<>();
        storeGoodsVoList.add(info);
        Map<String, Object> extendsMap = orderManager.getExtends(storeGoodsVoList, address, hospitalSend,
                freightForecastForm.getChannel(),null,storeGoodsProductVoList);

        List<FreightForecastDeliveryDto> forecastDeliveryDtoList=new ArrayList<>();
        List<FreightForecastDeliveryDto> returnDeliveryDtoList=new ArrayList<>();
        //普通配送
        JSONObject deliveryService=JSON.parseObject(JSON.toJSONString(extendsMap.get("deliveryService"))) ;
        Object normal=deliveryService.get("normal");
        if(ObjectUtil.isNotNull(normal)){
            FreightForecastDeliveryDto normalDto = assambleDeliveryDto("普通配送", normal, storeGoodsVoList,
                    address, store, storeGoodsProductVoList,false,false);
            if(storeGoodsVoList.get(0).getLogisticsType()==1&&storeGoodsVoList.get(0).getSameCitySendType()==1){
                AgedmallFreightTemplate freightTemplate = agedmallFreightTemplateService.findById(storeGoodsVoList.get(0).getSameCity().longValue());
                if(freightTemplate!=null&&freightTemplate.getCanUrgent()==1){
                    normalDto.setIsUrgent(1);
                    String[] split = freightTemplate.getUrgentPay().split(",");
                    normalDto.setUrgentPrice(new BigDecimal(split[0]));
                }
            }
            forecastDeliveryDtoList.add(normalDto);
        }

        //自提
        Object self=deliveryService.get("self");
        if(ObjectUtil.isNotNull(self)){
            FreightForecastDeliveryDto selfDto = assambleDeliveryDto("自提", self, storeGoodsVoList,
                    address, store,storeGoodsProductVoList,false,true);
            forecastDeliveryDtoList.add(selfDto);
        }

        //医院配送
//        Object hospital=extendsMap.get("hospital");
//        if(ObjectUtil.isNotNull(hospital)){
//
//        }

        //-----------取回--------------

        //送货到店
        FreightForecastDeliveryDto sendToStore = assambleDeliveryDto("送货到店", null, storeGoodsVoList,
                address, store,storeGoodsProductVoList,true,true);
        sendToStore.setPrice(BigDecimal.ZERO);
        returnDeliveryDtoList.add(sendToStore);

        //上门取件
        FreightForecastDeliveryDto selfGoods = assambleDeliveryDto("上门取件", null, storeGoodsVoList,
                address, store,storeGoodsProductVoList,true,false);
        BigDecimal price=BigDecimal.ZERO;
        if(info.getCloudStockId()!=null){
            price=orderCalcService.getCloudFeight(info,address.getProvinceId(),info.getCloudStockId(),true);
        }
        else{
            price=orderCalcService.getFeight(info,store,address.getLng(),address.getLat(),true);
        }
        selfGoods.setPrice(price);
        returnDeliveryDtoList.add(selfGoods);

        //自行寄回
        FreightForecastDeliveryDto sendBack = assambleDeliveryDto("自行寄回", null, storeGoodsVoList,
                address, store,storeGoodsProductVoList,true,true);
        sendBack.setPrice(BigDecimal.ZERO);
        returnDeliveryDtoList.add(sendBack);



        map.put("isCalcSuccess",1);
        map.put("deliveryList",forecastDeliveryDtoList);
        map.put("returnList",returnDeliveryDtoList);
        return RespUtil.success(map);
    }

    /**
     * 无需配送费免费模板
     */
    public String freeHtml(){
        StringBuilder builder=new StringBuilder();
        builder.append("<div>");
        builder.append("统一运费￥0");
        builder.append("</div>");
        return builder.toString();
    }


    public FreightForecastDeliveryDto assambleDeliveryDto(String name,Object bean,List<StoreGoodsVo> storeGoodsVoList,
                                                          LitemallAddress address,AgedmallStore store,List<StoreGoodsProductVo> specificationsList,boolean pickUp,boolean isFree){
        FreightForecastDeliveryDto freightForecastDeliveryDto=new FreightForecastDeliveryDto();
        if(ObjectUtil.isNotNull(bean)){
            JSONObject jsonObject = (JSONObject) bean;
            BigDecimal price=new BigDecimal(jsonObject.get("price").toString());
            if(isFree){
                freightForecastDeliveryDto.setPrice(BigDecimal.ZERO);
            }
            else{
                freightForecastDeliveryDto.setPrice(price);
            }

        }
        freightForecastDeliveryDto.setName(name);
        FreightDetail freightDetail=new FreightDetail();
        FeightFeeResult feightFeeResult = orderCalcService.calFeightFee(storeGoodsVoList, address, store);
        List<FreightGoodsDto> freightGoodsDtoList = feightFeeResult.getFreightGoodsDtoList();
        BigDecimal totalPrice=BigDecimal.ZERO;
        for (int i = 0; i < freightGoodsDtoList.size(); i++) {
            //获取skuName
            for (int j = 0; j < specificationsList.size(); j++) {
                if(specificationsList.get(j).getStoreGoodsId().equals(freightGoodsDtoList.get(i).getId())) {
                    List<LitemallGoodsProductSpecification> specifications
                            = JSON.parseArray(specificationsList.get(j).getSpecifications(), LitemallGoodsProductSpecification.class);
                    StringBuffer sku = new StringBuffer();
                    for (LitemallGoodsProductSpecification lgs : specifications) {
                        StringBuffer sb = new StringBuffer();
                        sb.append(lgs.getInfoName()).append(":").append(lgs.getName());
                        sku.append(sb).append(";");
                    }
                    if(!isFree){
                        totalPrice = totalPrice.add(freightGoodsDtoList.get(i).getPrice());
                    }
                    else{
                        freightGoodsDtoList.get(i).setPrice(BigDecimal.ZERO);
                    }

                    String spiltSku = sku.substring(0, sku.length() - 1);
                    freightGoodsDtoList.get(i).setSkuName(spiltSku);
                }
            }

            for (int j = 0; j < storeGoodsVoList.size(); j++) {
                if(storeGoodsVoList.get(j).getStoreGoodsId().equals(freightGoodsDtoList.get(i).getId())){
                    String deliveryMessageDesc="";
                    if(isFree){
                        deliveryMessageDesc=freeHtml();
                    }
                    else{
                        deliveryMessageDesc = orderCalcService.getDeliveryMessageDesc(storeGoodsVoList.get(j), address.getProvinceId(), storeGoodsVoList.get(j).getCloudStockId(),
                                pickUp, store, address.getLng(), address.getLat());
                    }
                    // 单独增加返回运费计算明细
                    freightGoodsDtoList.get(i).setFreightHtml(deliveryMessageDesc);
                }
            }

        }

        freightDetail.setGoodsList(freightGoodsDtoList);
        freightDetail.setTotalPrice(totalPrice);
        freightForecastDeliveryDto.setFreightDetail(freightDetail);

        return freightForecastDeliveryDto;
    }




}
